X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FSound%2Ffg_fx.cxx;h=5537bb1195b80743a59005658aa6499ed1829383;hb=db89cf202adc795b27e1bbf85162e8ec137a760d;hp=c5df626842e4b2c8972a4ae8f9029dc6b6957c5a;hpb=65701b43dc35e256797d98789f04d1ce89028437;p=flightgear.git diff --git a/src/Sound/fg_fx.cxx b/src/Sound/fg_fx.cxx index c5df62684..5537bb119 100644 --- a/src/Sound/fg_fx.cxx +++ b/src/Sound/fg_fx.cxx @@ -3,7 +3,7 @@ // Started by David Megginson, October 2001 // (Reuses some code from main.cxx, probably by Curtis Olson) // -// Copyright (C) 2001 Curtis L. Olson - curt@flightgear.org +// Copyright (C) 2001 Curtis L. Olson - http://www.flightgear.org/~curt // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -21,189 +21,99 @@ // // $Id$ -#include // FIXME: remove direct dependencies -#include
+#ifdef _MSC_VER +#pragma warning (disable: 4786) +#endif -#include "fg_fx.hxx" +#ifdef HAVE_CONFIG_H +# include +#endif +#include +#include +#ifdef __BORLANDC__ +# define exception c_exception +#endif +#include +#include +#include -static const char * engine_names[FGFX::MAX_ENGINES] = { - "engine0", - "engine1" -}; +#include
-static const char * crank_names[FGFX::MAX_ENGINES] = { - "crank0", - "crank1" -}; +#include "fg_fx.hxx" -FGFX::FGFX () - : _old_flap_position(0), - _old_gear_position(0), - _wind(0), - _stall(0), - _rumble(0), - _flaps(0), - _gear_up(0), - _gear_dn(0), - _squeal(0), - _click(0), - _stall_warning_prop(0), - _flaps_prop(0), - _gear_prop(0) +FGFX::FGFX () : + last_pause( true ), + last_volume( 0.0 ), + _pause( fgGetNode("/sim/sound/pause") ), + _volume( fgGetNode("/sim/sound/volume") ) { - for (int i = 0; i < MAX_ENGINES; i++) { - _engine[i] = 0; - _crank[i] = 0; - _engine_running_prop[i] = 0; - _engine_cranking_prop[i] = 0; - } } FGFX::~FGFX () { - // FIXME: is this right, or does the - // sound manager assume pointer ownership? - for (int i = 0; i < MAX_ENGINES; i++) { - delete _engine[i]; - delete _crank[i]; - } - delete _wind; - delete _stall; - delete _rumble; + unsigned int i; + for ( i = 0; i < _sound.size(); i++ ) { + delete _sound[i]; + } + _sound.clear(); - delete _flaps; - delete _gear_up; - delete _gear_dn; - delete _squeal; - delete _click; + while ( _samplequeue.size() > 0 ) { + delete _samplequeue.front(); + _samplequeue.pop(); + } } - void -FGFX::init () +FGFX::init() { - FGSoundMgr * mgr = globals->get_soundmgr(); - int i; - - // - // Create and add engine-related sounds. - // - for (i = 0; i < MAX_ENGINES; i++) { - // Engine - _engine[i] = - new FGSimpleSound(fgGetString("/sim/sounds/engine/path", - "Sounds/wasp.wav")); - _engine[i]->set_volume(fgGetFloat("/sim/sounds/engine/volume", 1.0)); - _engine[i]->set_pitch(fgGetFloat("/sim/sounds/engine/pitch", 1.0)); - mgr->add(_engine[i], engine_names[i]); - - // Starter - _crank[i] = new FGSimpleSound(fgGetString("/sim/sounds/cranking/path", - "Sounds/cranking.wav")); - _crank[i]->set_volume(fgGetFloat("/sim/sounds/cranking/volume", 0.5)); - _crank[i]->set_pitch(fgGetFloat("/sim/sounds/cranking/pitch", 1.00)); - mgr->add(_crank[i], crank_names[i]); - } - - - // - // Create and add the wind noise. - // - _wind = new FGSimpleSound(fgGetString("/sim/sounds/wind/path", - "Sounds/wind.wav")); - _wind->set_volume(fgGetFloat("/sim/sounds/wind/volume", 1.0)); - _wind->set_pitch(fgGetFloat("/sim/sounds/wind/pitch", 1.0)); - mgr->add(_wind, "wind"); - - - // - // Create and add the stall noise. - // - _stall = new FGSimpleSound(fgGetString("/sim/sounds/stall/path", - "Sounds/stall.wav")); - _stall->set_volume(fgGetFloat("/sim/sounds/stall/volume", 1.0)); - _stall->set_pitch(fgGetFloat("/sim/sounds/stall/pitch", 1.0)); - mgr->add(_stall, "stall"); - - // - // Create and add the rumble noise. - // - _rumble = new FGSimpleSound(fgGetString("/sim/sounds/rumble/path", - "Sounds/rumble.wav")); - _rumble->set_volume(fgGetFloat("/sim/sounds/rumble/volume", 1.0)); - _rumble->set_pitch(fgGetFloat("/sim/sounds/rumble/pitch", 1.0)); - mgr->add(_rumble, "rumble"); - - - // - // Create and add the flaps noise - // - _flaps = new FGSimpleSound(fgGetString("/sim/sounds/flaps/path", - "Sounds/flaps.wav")); - _flaps->set_volume(fgGetFloat("/sim/sounds/flaps/volume", 0.25)); - _flaps->set_pitch(fgGetFloat("/sim/sounds/flaps/pitch", 1.0)); - mgr->add(_flaps, "flaps"); - - // - // Create and add the gear noises. - // - _gear_up = new FGSimpleSound(fgGetString("/sim/sounds/gear-up/path", - "Sounds/gear-up.wav")); - _gear_dn = new FGSimpleSound(fgGetString("/sim/sounds/gear-down/path", - "Sounds/gear-dn.wav")); - _gear_up->set_volume(fgGetFloat("/sim/sounds/gear-up/volume", 1.0)); - _gear_dn->set_volume(fgGetFloat("/sim/sounds/gear-down/volume", 1.0)); - _gear_up->set_pitch(fgGetFloat("/sim/sounds/gear-up/pitch", 1.0)); - _gear_dn->set_pitch(fgGetFloat("/sim/sounds/gear-down/pitch", 1.0)); - mgr->add(_gear_up, "gear-up"); - mgr->add(_gear_dn, "gear-down"); - - // - // Create and add the squeal noise. - // - _squeal = new FGSimpleSound(fgGetString("/sim/sounds/squeal/path", - "Sounds/squeal.wav")); - _squeal->set_volume(fgGetFloat("/sim/sounds/squeal/volume", 1.0)); - _squeal->set_pitch(fgGetFloat("/sim/sounds/squeal/pitch", 1.0)); - mgr->add(_squeal, "squeal"); - - // - // Simplistic wheel spin model for audio effect purposes only. We - // don't want to play a full squeel, if the wheel has only departed - // from the ground for a split second. - // - for (i = 0; i < MAX_GEAR; i++) { - _wheel_spin[i] = 0.0; - } - - // - // Create and add the click noise. - _click = new FGSimpleSound(fgGetString("/sim/sounds/click/path", - "Sounds/click.wav")); - _flaps->set_volume(fgGetFloat("/sim/sounds/click/volume", 1.0)); - _flaps->set_pitch(fgGetFloat("/sim/sounds/click/pitch", 1.0)); - mgr->add(_click, "click"); - - - //////////////////////////////////////////////////////////////////// - // Grab some properties. - //////////////////////////////////////////////////////////////////// - - for (i = 0; i < MAX_ENGINES; i++) { - char buf[100]; - sprintf(buf, "/engines/engine[%d]/running", i); - _engine_running_prop[i] = fgGetNode(buf, true); - sprintf(buf, "/engines/engine[%d]/cranking", i); - _engine_cranking_prop[i] = fgGetNode(buf, true); - } - _stall_warning_prop = fgGetNode("/sim/aero/alarms/stall-warning", true); - _vc_prop = fgGetNode("/velocities/airspeed-kt", true); - _flaps_prop = fgGetNode("/controls/flaps", true); - _gear_prop = fgGetNode("/controls/gear-down", true); + SGPropertyNode *node = fgGetNode("/sim/sound", true); + int i; + + string path_str = node->getStringValue("path"); + SGPath path( globals->get_fg_root() ); + if (path_str.empty()) { + SG_LOG(SG_GENERAL, SG_ALERT, "Incorrect path in configuration file."); + return; + } + + path.append(path_str.c_str()); + SG_LOG(SG_GENERAL, SG_INFO, "Reading sound " << node->getName() + << " from " << path.str()); + + SGPropertyNode root; + try { + readProperties(path.str(), &root); + } catch (const sg_exception &) { + SG_LOG(SG_GENERAL, SG_ALERT, + "Incorrect path specified in configuration file"); + return; + } + + node = root.getNode("fx"); + for (i = 0; i < node->nChildren(); i++) { + SGXmlSound *sound = new SGXmlSound(); + + try { + sound->init(globals->get_props(), node->getChild(i), + globals->get_soundmgr(), globals->get_fg_root()); + + _sound.push_back(sound); + } catch ( sg_io_exception &e ) { + SG_LOG(SG_GENERAL, SG_ALERT, e.getFormattedMessage()); + delete sound; + } + } } +void +FGFX::reinit() +{ + _sound.clear(); + init(); +}; + void FGFX::bind () { @@ -215,215 +125,74 @@ FGFX::unbind () } void -FGFX::update (int dt) +FGFX::update (double dt) { - FGSoundMgr * mgr = globals->get_soundmgr(); - int i; - - //////////////////////////////////////////////////////////////////// - // Update the engine sound. - //////////////////////////////////////////////////////////////////// - - for (i = 0; i < MAX_ENGINES; i++) { - - if (cur_fdm_state->get_num_engines() > 0 && - _engine_running_prop[i]->getBoolValue()) { - // pitch corresponds to rpm - // volume corresponds to manifold pressure - - double rpm_factor; - if ( cur_fdm_state->get_num_engines() > 0 ) - rpm_factor = cur_fdm_state->get_engine(i)->get_RPM() / 2500.0; - else - rpm_factor = 1.0; - - double pitch = 0.3 + rpm_factor * 3.0; - - // don't run at absurdly slow rates -- not realistic - // and sounds bad to boot. :-) - if (pitch < 0.7) - pitch = 0.7; - if (pitch > 5.0) - pitch = 5.0; - - double mp_factor; - if ( cur_fdm_state->get_num_engines() > 0 ) - mp_factor = - cur_fdm_state->get_engine(i)->get_Manifold_Pressure() / 100; - else - mp_factor = 0.3; - - double volume = 0.15 + mp_factor / 2.0; - - if (volume < 0.15) - volume = 0.15; - if (volume > 0.5) - volume = 0.5; - - _engine[i]->set_pitch( pitch ); - _engine[i]->set_volume( volume ); - set_playing(engine_names[i], true); - } else { - set_playing(engine_names[i], false); + SGSoundMgr *smgr = globals->get_soundmgr(); + + // command sound manger + bool pause = _pause->getBoolValue(); + if ( pause != last_pause ) { + if ( pause ) { + smgr->pause(); + } else { + smgr->resume(); + } + last_pause = pause; } - // FIXME - set_playing(crank_names[i], _engine_cranking_prop[i]->getBoolValue()); - } - - - //////////////////////////////////////////////////////////////////// - // Update the wind noise. - //////////////////////////////////////////////////////////////////// - - // The wind sound is airspeed and altitude - // dependent. The wind noise should become - // silent at about 65000 feet, and is based - // on a logarithmic scale. - float rel_wind = cur_fdm_state->get_V_rel_wind(); // FPS - float alt_vol = 1-log(cur_fdm_state->get_Altitude()/65000.0)/4.81; - if ((rel_wind > 2.0) && (alt_vol > 0.2)) { - float volume = rel_wind/937; - double pitch = 1.0+(rel_wind/53.0); - _wind->set_volume(volume*alt_vol/2); - _wind->set_pitch(pitch); - set_playing("wind", true); - } else { - set_playing("wind", false); - } - - - //////////////////////////////////////////////////////////////////// - // Update the stall horn. - //////////////////////////////////////////////////////////////////// - - double stall = _stall_warning_prop->getDoubleValue(); - double vc = _vc_prop->getDoubleValue(); - if (stall > 0.0 && vc > 30.0) { - _stall->set_volume(stall); - set_playing("stall", true); - } else { - set_playing("stall", false); - } - - - //////////////////////////////////////////////////////////////////// - // Update the rumble. - //////////////////////////////////////////////////////////////////// - - float totalGear = min(cur_fdm_state->get_num_gear(), int(MAX_GEAR)); - float gearOnGround = 0; - - - // Calculate whether a squeal is - // required, and set the volume. - // Currently, the squeal volume is the - // current local down velocity in feet - // per second divided by 10.0, and - // will not be played if under 0.1. - - // FIXME: take rotational velocities - // into account as well. - for (i = 0; i < totalGear; i++) { - // cout << "air speed = " << cur_fdm_state->get_V_equiv_kts(); - // cout << " wheel " << i << " speed = " << _wheel_spin[i]; - if (cur_fdm_state->get_gear_unit(i)->GetWoW()) { - gearOnGround++; - if (!_gear_on_ground[i]) { - // wheel just touched down - // 3 parts horizontal velocity + 1 part vertical velocity - double squeal_volume = 0.75 * cur_fdm_state->get_V_equiv_kts() / 90.0 - + 0.25 * cur_fdm_state->get_V_down() / 5.0; - - // scale volume by difference between wheel spin speed and - // ground speed - double diff = fabs( cur_fdm_state->get_V_equiv_kts() - - _wheel_spin[i] ); - // cout << " speed diff = " << diff; - double scale_factor = 0.0; - if ( diff > 10 ) { - scale_factor = ( diff - 10.0 ) / 30.0f; - if ( scale_factor > 1.0 ) { scale_factor = 1.0; } - } - // cout << " scale_factor = " << scale_factor; - squeal_volume *= scale_factor; - - if (squeal_volume > 0.1) { - _squeal->set_volume(squeal_volume); - _squeal->set_pitch(1.25); - mgr->play_once("squeal"); - } - _gear_on_ground[i] = true; - } - // cout << " wow"; - _wheel_spin[i] = cur_fdm_state->get_V_equiv_kts(); - } else { - // cout << " airborn"; - _gear_on_ground[i] = false; - /* fix me: wheel spindown is currently frame rate dependent which - it shouldn't be */ - _wheel_spin[i] -= 0.2; - if ( _wheel_spin[i] < 0.0 ) { _wheel_spin[i] = 0.0; } + // process mesage queue + const string msgid = "Sequential Audio Message"; + bool is_playing = false; + if ( smgr->exists( msgid ) ) { + if ( smgr->is_playing( msgid ) ) { + // still playing, do nothing + is_playing = true; + } else { + // current message finished, stop and remove + smgr->stop( msgid ); // removes source + smgr->remove( msgid ); // removes buffer + } } - // cout << endl; - } - - // Now, if any of the gear is in - // contact with the ground play the - // rumble sound. The volume is a - // logarthmic scale of the absolute - // velocity in knots divided by 12.0. - // No rumble will be played if the - // velocity is under ~0.25 kt. - double speed = cur_fdm_state->get_V_equiv_kts(); - if (gearOnGround > 0 && speed > 0.5) { - double volume = 2.0 * (gearOnGround/totalGear) * log(speed)/12; //(speed/60.0); - _rumble->set_volume(volume); - set_playing("rumble", true); - } else { - set_playing("rumble", false); - } - - - //////////////////////////////////////////////////////////////////// - // Check for flap movement. - //////////////////////////////////////////////////////////////////// - - double flap_position = _flaps_prop->getDoubleValue(); - if (fabs(flap_position - _old_flap_position) > 0.1) { - mgr->play_once("flaps"); - _old_flap_position = flap_position; - } - - - //////////////////////////////////////////////////////////////////// - // Check for gear movement. - //////////////////////////////////////////////////////////////////// - - double gear_position = _gear_prop->getDoubleValue(); - if (gear_position != _old_gear_position) { - if (gear_position < _old_gear_position) { - mgr->play_once("gear-up"); - } else { - mgr->play_once("gear-down"); + if ( !is_playing ) { + // message queue idle, add next sound if we have one + if ( _samplequeue.size() > 0 ) { + smgr->add( _samplequeue.front(), msgid ); + _samplequeue.pop(); + smgr->play_once( msgid ); + } } - _old_gear_position = gear_position; - } - // TODO: click + double volume = _volume->getDoubleValue(); + if ( volume != last_volume ) { + smgr->set_volume( volume ); + last_volume = volume; + } + if ( !pause ) { + // update sound effects if not paused + for ( unsigned int i = 0; i < _sound.size(); i++ ) { + _sound[i]->update(dt); + } + } } - +/** + * add a sound sample to the message queue which is played sequentially + * in order. + */ void -FGFX::set_playing (const char * soundName, bool state) +FGFX::play_message( SGSoundSample *_sample ) { - FGSoundMgr * mgr = globals->get_soundmgr(); - bool playing = mgr->is_playing(soundName); - if (state && !playing) - mgr->play_looped(soundName); - else if (!state && playing) - mgr->stop(soundName); + _sample->set_volume( 1.0 ); + _samplequeue.push( _sample ); } +void +FGFX::play_message( const string path, const string fname ) +{ + SGSoundSample *sample; + sample = new SGSoundSample( path.c_str(), fname.c_str() ); + play_message( sample ); +} + // end of fg_fx.cxx