diff --git a/Globals.cpp b/Globals.cpp index d0380273..862353b7 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -151,6 +151,24 @@ global_settings::ConfigParse(cParser &Parser) { Parser >> RadioVolume; RadioVolume = clamp( RadioVolume, 0.f, 1.f ); } + else if( token == "sound.volume.vehicle" ) { + // selected device for audio renderer + Parser.getTokens(); + Parser >> VehicleVolume; + VehicleVolume = clamp( VehicleVolume, 0.f, 1.f ); + } + else if( token == "sound.volume.positional" ) { + // selected device for audio renderer + Parser.getTokens(); + Parser >> EnvironmentPositionalVolume; + EnvironmentPositionalVolume = clamp( EnvironmentPositionalVolume, 0.f, 1.f ); + } + else if( token == "sound.volume.ambient" ) { + // selected device for audio renderer + Parser.getTokens(); + Parser >> EnvironmentAmbientVolume; + EnvironmentAmbientVolume = clamp( EnvironmentAmbientVolume, 0.f, 1.f ); + } // else if (str==AnsiString("renderalpha")) //McZapkie-1312302 - dwuprzebiegowe renderowanie // bRenderAlpha=(GetNextSymbol().LowerCase()==AnsiString("yes")); else if (token == "physicslog") @@ -987,6 +1005,9 @@ global_settings::export_as_text( std::ostream &Output ) const { export_as_text( Output, "sound.openal.renderer", AudioRenderer ); export_as_text( Output, "sound.volume", AudioVolume ); export_as_text( Output, "sound.volume.radio", RadioVolume ); + export_as_text( Output, "sound.volume.vehicle", VehicleVolume ); + export_as_text( Output, "sound.volume.positional", EnvironmentPositionalVolume ); + export_as_text( Output, "sound.volume.ambient", EnvironmentAmbientVolume ); export_as_text( Output, "physicslog", WriteLogFlag ); export_as_text( Output, "fullphysics", FullPhysics ); export_as_text( Output, "debuglog", iWriteLogEnabled ); diff --git a/Globals.h b/Globals.h index 75803bab..c3aae2cd 100644 --- a/Globals.h +++ b/Globals.h @@ -155,6 +155,9 @@ struct global_settings { bool bSoundEnabled{ true }; float AudioVolume{ 1.f }; float RadioVolume{ 0.75f }; + float VehicleVolume{ 1.0f }; + float EnvironmentPositionalVolume{ 1.0f }; + float EnvironmentAmbientVolume{ 1.0f }; std::string AudioRenderer; // input float fMouseXScale{ 1.5f }; diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 4c604f93..2fc246db 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -8296,7 +8296,7 @@ TMoverParameters::update_doors( double const Deltatime ) { auto const ispowered { ( Doors.voltage == 0 ? true : - Doors.voltage == 24 ? Power24vIsAvailable : + Doors.voltage == 24 ? ( Power24vIsAvailable || Power110vIsAvailable ) : Doors.voltage == 110 ? Power110vIsAvailable : false ) }; diff --git a/audiorenderer.cpp b/audiorenderer.cpp index e4412b41..4366e80f 100644 --- a/audiorenderer.cpp +++ b/audiorenderer.cpp @@ -21,6 +21,7 @@ http://mozilla.org/MPL/2.0/. namespace audio { openal_renderer renderer; +bool event_volume_change { false }; float const EU07_SOUND_CUTOFFRANGE { 3000.f }; // 2750 m = max expected emitter spawn range, plus safety margin float const EU07_SOUND_VELOCITYLIMIT { 250 / 3.6f }; // 343 m/sec ~= speed of sound; arbitrary limit of 250 km/h @@ -133,8 +134,7 @@ openal_source::sync_with( sound_properties const &State ) { // NOTE: velocity at this point can be either listener velocity for global sounds, actual sound velocity, or 0 if sound position is yet unknown ::alSourcefv( id, AL_VELOCITY, glm::value_ptr( sound_velocity ) ); // location - properties.location = State.location; - sound_distance = properties.location - glm::dvec3 { Global.pCamera.Pos }; + sound_distance = State.location - glm::dvec3 { Global.pCamera.Pos }; if( sound_range != -1 ) { // range cutoff check for songs other than 'unlimited' // NOTE: since we're comparing squared distances we can ignore that sound range can be negative @@ -156,18 +156,23 @@ openal_source::sync_with( sound_properties const &State ) { ::alSourcefv( id, AL_POSITION, glm::value_ptr( glm::vec3() ) ); } // gain + auto const gain { + State.gain + * State.soundproofing + * ( State.category == sound_category::vehicle ? Global.VehicleVolume : + State.category == sound_category::local ? Global.EnvironmentPositionalVolume : + State.category == sound_category::ambient ? Global.EnvironmentAmbientVolume : + 1.f ) }; if( ( State.gain != properties.gain ) - || ( State.soundproofing_stamp != properties.soundproofing_stamp ) ) { + || ( State.soundproofing_stamp != properties.soundproofing_stamp ) + || ( audio::event_volume_change ) ) { // gain value has changed - properties.gain = State.gain; - properties.soundproofing = State.soundproofing; - properties.soundproofing_stamp = State.soundproofing_stamp; - ::alSourcef( id, AL_GAIN, properties.gain * properties.soundproofing ); + ::alSourcef( id, AL_GAIN, gain ); auto const range { ( sound_range >= 0 ? sound_range : 5 ) }; // range of -1 means sound of unlimited range, positioned at the listener - ::alSourcef( id, AL_REFERENCE_DISTANCE, range * ( 1.f / 16.f ) * properties.soundproofing ); + ::alSourcef( id, AL_REFERENCE_DISTANCE, range * ( 1.f / 16.f ) * State.soundproofing ); } if( sound_range != -1 ) { auto const rangesquared { sound_range * sound_range }; @@ -183,17 +188,17 @@ openal_source::sync_with( sound_properties const &State ) { clamp( ( distancesquared - rangesquared ) / ( fadedistance * fadedistance ), 0.f, 1.f ) ) }; - ::alSourcef( id, AL_GAIN, properties.gain * properties.soundproofing * rangefactor ); + ::alSourcef( id, AL_GAIN, gain * rangefactor ); } is_in_range = ( distancesquared <= rangesquared ); } // pitch if( State.pitch != properties.pitch ) { // pitch value has changed - properties.pitch = State.pitch; - - ::alSourcef( id, AL_PITCH, clamp( properties.pitch * pitch_variation, 0.1f, 10.f ) ); + ::alSourcef( id, AL_PITCH, clamp( State.pitch * pitch_variation, 0.1f, 10.f ) ); } + // all synced up + properties = State; sync = sync_state::good; } @@ -341,16 +346,7 @@ openal_renderer::update( double const Deltatime ) { ::alListenerfv( AL_ORIENTATION, reinterpret_cast( orientation ) ); // velocity if( Deltatime > 0 ) { -/* - glm::dvec3 const listenerposition { Global.pCamera.Pos }; - glm::dvec3 const listenermovement { listenerposition - m_listenerposition }; - m_listenerposition = listenerposition; - m_listenervelocity = ( - glm::length( listenermovement ) < 1000.0 ? // large jumps are typically camera changes - limit_velocity( listenermovement / Deltatime ) : - glm::vec3() ); -*/ - auto cameramove{ glm::dvec3{ Global.pCamera.Pos - m_camerapos} }; + auto cameramove { glm::dvec3{ Global.pCamera.Pos - m_camerapos} }; m_camerapos = Global.pCamera.Pos; // intercept sudden user-induced camera jumps... // ...from free fly mode change @@ -396,6 +392,8 @@ openal_renderer::update( double const Deltatime ) { ++source; } } + // reset potentially used volume change flag + audio::event_volume_change = false; } // returns an instance of implementation-side part of the sound emitter diff --git a/audiorenderer.h b/audiorenderer.h index 84543c15..036ee7d3 100644 --- a/audiorenderer.h +++ b/audiorenderer.h @@ -20,13 +20,21 @@ class sound_source; using uint32_sequence = std::vector; +enum class sound_category : unsigned int { + unknown = 0, // source gain is unaltered + vehicle, // source gain is altered by vehicle sound volume modifier + local, // source gain is altered by positional environment sound volume modifier + ambient, // source gain is altered by ambient environment sound volume modifier +}; + // sound emitter state sync item struct sound_properties { glm::dvec3 location; + float pitch { 1.f }; + sound_category category { sound_category::unknown }; float gain { 1.f }; float soundproofing { 1.f }; std::uintptr_t soundproofing_stamp { ~( std::uintptr_t{ 0 } ) }; - float pitch { 1.f }; }; enum class sync_state { @@ -165,6 +173,7 @@ private: }; extern openal_renderer renderer; +extern bool event_volume_change; diff --git a/driveruipanels.cpp b/driveruipanels.cpp index 5522ea35..556b4b7f 100644 --- a/driveruipanels.cpp +++ b/driveruipanels.cpp @@ -572,10 +572,8 @@ debug_panel::render() { ImGui::Checkbox( "Debug Traction", &DebugTractionFlag ); } render_section( "Camera", m_cameralines ); - if( true == render_section( "Gfx Renderer", m_rendererlines ) ) { - // reflection fidelity - ImGui::SliderInt( ( to_string( Global.reflectiontune.fidelity ) + "###reflectionfidelity" ).c_str(), &Global.reflectiontune.fidelity, 0, 2, "Reflection fidelity" ); - } + render_section( "Gfx Renderer", m_rendererlines ); + render_section_settings(); // toggles ImGui::Separator(); ImGui::Checkbox( "Debug Mode", &DebugModeFlag ); @@ -1266,6 +1264,36 @@ debug_panel::render_section( std::string const &Header, std::vector c return true; } +bool +debug_panel::render_section_settings() { + + if( false == ImGui::CollapsingHeader( "Settings" ) ) { return false; } + + ImGui::PushStyleColor( ImGuiCol_Text, { Global.UITextColor.r, Global.UITextColor.g, Global.UITextColor.b, Global.UITextColor.a } ); + ImGui::TextUnformatted( "Graphics" ); + ImGui::PopStyleColor(); + // reflection fidelity + ImGui::SliderInt( ( to_string( Global.reflectiontune.fidelity ) + "###reflectionfidelity" ).c_str(), &Global.reflectiontune.fidelity, 0, 2, "Reflection fidelity" ); + + ImGui::PushStyleColor( ImGuiCol_Text, { Global.UITextColor.r, Global.UITextColor.g, Global.UITextColor.b, Global.UITextColor.a } ); + ImGui::TextUnformatted( "Sound" ); + ImGui::PopStyleColor(); + // audio volume sliders + ImGui::SliderFloat( ( to_string( static_cast( Global.AudioVolume * 100 ) ) + "%###volumemain" ).c_str(), &Global.AudioVolume, 0.0f, 2.0f, "Main audio volume" ); + if( ImGui::SliderFloat( ( to_string( static_cast( Global.VehicleVolume * 100 ) ) + "%###volumevehicle" ).c_str(), &Global.VehicleVolume, 0.0f, 1.0f, "Vehicle sounds" ) ) { + audio::event_volume_change = true; + } + if( ImGui::SliderFloat( ( to_string( static_cast( Global.EnvironmentPositionalVolume * 100 ) ) + "%###volumepositional" ).c_str(), &Global.EnvironmentPositionalVolume, 0.0f, 1.0f, "Positional sounds" ) ) { + audio::event_volume_change = true; + } + if( ImGui::SliderFloat( ( to_string( static_cast( Global.EnvironmentAmbientVolume * 100 ) ) + "%###volumeambient" ).c_str(), &Global.EnvironmentAmbientVolume, 0.0f, 1.0f, "Ambient sounds" ) ) { + audio::event_volume_change = true; + } + ImGui::PushStyleColor( ImGuiCol_Text, { Global.UITextColor.r, Global.UITextColor.g, Global.UITextColor.b, Global.UITextColor.a } ); + + return true; +} + void transcripts_panel::update() { diff --git a/driveruipanels.h b/driveruipanels.h index d6bb5225..f9e78575 100644 --- a/driveruipanels.h +++ b/driveruipanels.h @@ -96,6 +96,7 @@ private: // renders provided lines, under specified collapsing header bool render_section( std::string const &Header, std::vector const &Lines ); bool render_section_scenario(); + bool render_section_settings(); // members std::array m_buffer; input_data m_input; diff --git a/eu07.ico b/eu07.ico index af04013c..08173184 100644 Binary files a/eu07.ico and b/eu07.ico differ diff --git a/sound.cpp b/sound.cpp index d00e59a4..3c2a43ae 100644 --- a/sound.cpp +++ b/sound.cpp @@ -362,6 +362,13 @@ sound_source::play( int const Flags ) { m_stopend = true; } */ + // determine sound category + // TBD, TODO: user-configurable + m_properties.category = ( + m_owner ? sound_category::vehicle : + m_range < 0 ? sound_category::ambient : + sound_category::local ); + if( sound( sound_id::main ).buffer != null_handle ) { // basic variant: single main sound, with optional bookends play_basic(); @@ -986,7 +993,7 @@ sound_source::update_soundproofing() { case sound_placement::internal: { if( m_range >= -1 ) { // limited range sound m_properties.soundproofing = ( - soundproofingstamp == 0 ? + ( FreeFlyModeFlag || externalcamera ) ? EU07_SOUNDPROOFING_STRONG : // listener outside HACK: won't be true if active vehicle has open window ( simulation::Train->Dynamic() != m_owner ? EU07_SOUNDPROOFING_STRONG : // in another vehicle @@ -996,7 +1003,7 @@ sound_source::update_soundproofing() { } else { // global sound m_properties.soundproofing = ( - soundproofingstamp == 0 ? + ( FreeFlyModeFlag || externalcamera ) ? EU07_SOUNDPROOFING_GLOBAL_STRONG : // listener outside HACK: won't be true if active vehicle has open window ( simulation::Train->Dynamic() != m_owner ? EU07_SOUNDPROOFING_GLOBAL_VERYSTRONG : // in another vehicle @@ -1009,7 +1016,7 @@ sound_source::update_soundproofing() { case sound_placement::engine: { if( m_range >= -1 ) { // limited range sound m_properties.soundproofing = ( - externalcamera ? + ( FreeFlyModeFlag || externalcamera ) ? EU07_SOUNDPROOFING_SOME : // listener outside or has a window open ( simulation::Train->Dynamic() != m_owner ? EU07_SOUNDPROOFING_STRONG : // in another vehicle @@ -1019,7 +1026,7 @@ sound_source::update_soundproofing() { } else { // global sound m_properties.soundproofing = ( - ( externalcamera ) ? + ( FreeFlyModeFlag || externalcamera ) ? EU07_SOUNDPROOFING_GLOBAL_STRONG : // listener outside or has a window open ( simulation::Train->Dynamic() != m_owner ? EU07_SOUNDPROOFING_GLOBAL_VERYSTRONG : // in another vehicle diff --git a/version.h b/version.h index 2a344570..ded5d8e9 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 20 -#define VERSION_MINOR 908 +#define VERSION_MINOR 913 #define VERSION_REVISION 0