diff --git a/DynObj.cpp b/DynObj.cpp index 5a0d5017..268d2291 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -3622,7 +3622,35 @@ void TDynamicObject::RenderSounds() { || ( MoverParameters->EngineType == Dumb ) ) { // frequency calculation - frequency = rsSilnik.m_frequencyfactor * std::fabs( MoverParameters->enrot ) + rsSilnik.m_frequencyoffset; + auto normalizer { 1.f }; + // for combined sounds normalize frequency to 0-1 range + switch( MoverParameters->EngineType ) { + case DieselElectric: { + if( true == sConverter.is_combined() ) { + normalizer = MoverParameters->DElist[ MoverParameters->MainCtrlPosNo ].RPM / 60; + } + break; + } + case DieselEngine: { + if( true == rsSilnik.is_combined() ) { + normalizer = MoverParameters->dizel_nmax; + } + break; + } + case ElectricInductionMotor: { + if( true == rsSilnik.is_combined() ) { + // TODO: implement normalization/a way to calculate max expected engine rpm + } + break; + } + default: { + if( true == rsSilnik.is_combined() ) { + normalizer = MoverParameters->nmax; + } + break; + } + } + frequency = rsSilnik.m_frequencyfactor * std::abs( MoverParameters->enrot ) / std::max( 1.f, normalizer ) + rsSilnik.m_frequencyoffset; if( MoverParameters->EngineType == Dumb ) { frequency -= 0.2 * MoverParameters->EnginePower / ( 1 + MoverParameters->Power * 1000 ); } diff --git a/Globals.cpp b/Globals.cpp index c011d925..7ed2f2e2 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -40,6 +40,7 @@ float Global::FieldOfView = 45.0f; GLFWwindow *Global::window; bool Global::shiftState; bool Global::ctrlState; +bool Global::CabWindowOpen { false }; int Global::iCameraLast = -1; std::string Global::asVersion = "couldn't retrieve version string"; bool Global::ControlPicking = false; // indicates controls pick mode is enabled diff --git a/Globals.h b/Globals.h index 3e78723b..145ca3f7 100644 --- a/Globals.h +++ b/Globals.h @@ -235,6 +235,7 @@ public: static GLFWwindow *window; static bool shiftState; //m7todo: brzydko static bool ctrlState; + static bool CabWindowOpen; // controls sound attenuation between cab and outside static int iCameraLast; static std::string asVersion; // z opisem static bool ControlPicking; // indicates controls pick mode is active diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 1941e25c..2d6e084e 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -3737,8 +3737,8 @@ void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer) Voltage = RunningTraction.TractionVoltage * DirAbsolute; // ActiveDir*CabNo; } // bo nie dzialalo else if( ( EngineType == ElectricInductionMotor ) - || ( ( ( Couplers[ side::front ].CouplingFlag & ctrain_power ) == ctrain_power ) - || ( ( Couplers[ side::rear ].CouplingFlag & ctrain_power ) == ctrain_power ) ) ) { + || ( ( ( Couplers[ side::front ].CouplingFlag & ctrain_power ) == ctrain_power ) + || ( ( Couplers[ side::rear ].CouplingFlag & ctrain_power ) == ctrain_power ) ) ) { // potem ulepszyc! pantogtrafy! Voltage = std::max( @@ -4746,21 +4746,27 @@ double TMoverParameters::TractionForce(double dt) eimv[eimv_Uzsmax] = Min0R(Voltage - eimc[eimc_f_DU], tmp); eimv[eimv_fkr] = eimv[eimv_Uzsmax] / eimc[eimc_f_cfu]; - if ((dizel_fill < 0)) - eimv[eimv_Pmax] = eimc[eimc_p_Ph]; - else - eimv[eimv_Pmax] = - Min0R(eimc[eimc_p_Pmax], - 0.001 * Voltage * (eimc[eimc_p_Imax] - eimc[eimc_f_I0]) * Pirazy2 * - eimc[eimc_s_cim] / eimc[eimc_s_p] / eimc[eimc_s_cfu]); - eimv[eimv_FMAXMAX] = - 0.001 * square(Min0R(eimv[eimv_fkr] / Max0R(abs(enrot) * eimc[eimc_s_p] + - eimc[eimc_s_dfmax] * eimv[eimv_ks], - eimc[eimc_s_dfmax]), - 1) * - eimc[eimc_f_cfu] / eimc[eimc_s_cfu]) * - (eimc[eimc_s_dfmax] * eimc[eimc_s_dfic] * eimc[eimc_s_cim]) * - Transmision.Ratio * NPoweredAxles * 2.0 / WheelDiameter; + if( ( dizel_fill < 0 ) ) { + eimv[ eimv_Pmax ] = eimc[ eimc_p_Ph ]; + } + else { + eimv[ eimv_Pmax ] = + std::min( + eimc[ eimc_p_Pmax ], + 0.001 * Voltage * ( eimc[ eimc_p_Imax ] - eimc[ eimc_f_I0 ] ) * Pirazy2 * eimc[ eimc_s_cim ] / eimc[ eimc_s_p ] / eimc[ eimc_s_cfu ] ); + } + eimv[ eimv_FMAXMAX ] = + 0.001 + * square( + std::min( + 1.0, + eimv[ eimv_fkr ] / std::max( + abs( enrot ) * eimc[ eimc_s_p ] + eimc[ eimc_s_dfmax ] * eimv[ eimv_ks ], + eimc[ eimc_s_dfmax ] ) ) + * eimc[ eimc_f_cfu ] + / eimc[ eimc_s_cfu ] ) + * ( eimc[ eimc_s_dfmax ] * eimc[ eimc_s_dfic ] * eimc[ eimc_s_cim ] ) + * Transmision.Ratio * NPoweredAxles * 2.0 / WheelDiameter; if ((dizel_fill < 0)) { eimv[eimv_Fful] = std::min(eimc[eimc_p_Ph] * 3.6 / (Vel != 0.0 ? Vel : 0.001), @@ -4835,10 +4841,11 @@ double TMoverParameters::TractionForce(double dt) i = 0; while ((i < RlistSize - 1) && (DElist[i + 1].RPM < abs(tmpV))) i++; - RventRot = (abs(tmpV) - DElist[i].RPM) / - (DElist[i + 1].RPM - DElist[i].RPM) * - (DElist[i + 1].GenPower - DElist[i].GenPower) + - DElist[i].GenPower; + RventRot = + ( std::abs( tmpV ) - DElist[ i ].RPM ) + / std::max( 1.0, ( DElist[ i + 1 ].RPM - DElist[ i ].RPM ) ) + * ( DElist[ i + 1 ].GenPower - DElist[ i ].GenPower ) + + DElist[ i ].GenPower; } else RventRot = 0; diff --git a/World.cpp b/World.cpp index f850bda1..71593315 100644 --- a/World.cpp +++ b/World.cpp @@ -1116,6 +1116,8 @@ TWorld::Update_Camera( double const Deltatime ) { if( DebugCameraFlag ) { DebugCamera.Update(); } else { Camera.Update(); } // uwzględnienie ruchu wywołanego klawiszami + // reset window state, it'll be set again if applicable in a check below + Global::CabWindowOpen = false; if( ( Train != nullptr ) && ( Camera.Type == tp_Follow ) @@ -1128,6 +1130,8 @@ TWorld::Update_Camera( double const Deltatime ) { && ( (Console::Pressed( Global::Keys[ k_MechLeft ]) || (Console::Pressed( Global::Keys[ k_MechRight ]))))) { // jeśli lusterko lewe albo prawe (bez rzucania na razie) + Global::CabWindowOpen = true; + bool lr = Console::Pressed( Global::Keys[ k_MechLeft ] ); // Camera.Yaw powinno być wyzerowane, aby po powrocie patrzeć do przodu Camera.Pos = Controlled->GetPosition() + Train->MirrorPosition( lr ); // pozycja lusterka diff --git a/sound.cpp b/sound.cpp index 58cbdad3..3eda5d0b 100644 --- a/sound.cpp +++ b/sound.cpp @@ -331,7 +331,7 @@ void sound_source::play_combined() { // combined sound consists of table od samples, each sample associated with certain range of values of controlling variable // current value of the controlling variable is passed to the source with pitch() call - auto const soundpoint { clamp( m_properties.pitch * 100.f, 0.f, 100.f ) }; + auto const soundpoint { clamp( m_properties.pitch * 100.f, 0.f, 99.f ) }; for( std::uint32_t idx = 0; idx < m_soundchunks.size(); ++idx ) { auto const &soundchunk { m_soundchunks[ idx ] }; @@ -520,7 +520,7 @@ sound_source::update_combined( audio::openal_source &Source ) { if( ( soundhandle & sound_id::chunk ) != 0 ) { // for sound chunks, test whether the chunk should still be active given current value of the controlling variable - auto const soundpoint { clamp( m_properties.pitch * 100.f, 0.f, 100.f ) }; + auto const soundpoint { clamp( m_properties.pitch * 100.f, 0.f, 99.f ) }; auto const &soundchunk { m_soundchunks[ soundhandle ^ sound_id::chunk ] }; if( ( soundpoint < soundchunk.second.fadein ) || ( soundpoint > soundchunk.second.fadeout ) ) { @@ -598,7 +598,7 @@ sound_source::update_crossfade( sound_handle const Chunk ) { return; } - auto const soundpoint { clamp( m_properties.pitch * 100.f, 0.f, 100.f ) }; + auto const soundpoint { clamp( m_properties.pitch * 100.f, 0.f, 99.f ) }; // NOTE: direct access to implementation details ahead, kinda fugly auto const chunkindex { Chunk ^ sound_id::chunk }; @@ -607,16 +607,19 @@ sound_source::update_crossfade( sound_handle const Chunk ) { // relative pitch adjustment // pitch of each chunk is modified based on ratio of the chunk's pitch to that of its neighbour if( soundpoint < chunkdata.threshold ) { - // interpolate between the pitch of previous chunk and this chunk's base pitch, - // based on how far the current soundpoint is in the range of previous chunk - auto const &previouschunkdata{ m_soundchunks[ chunkindex - 1 ].second }; - m_properties.pitch = - interpolate( - previouschunkdata.pitch / chunkdata.pitch, - 1.f, - clamp( - ( soundpoint - previouschunkdata.threshold ) / ( chunkdata.threshold - previouschunkdata.threshold ), - 0.f, 1.f ) ); + + if( chunkindex > 0 ) { + // interpolate between the pitch of previous chunk and this chunk's base pitch, + // based on how far the current soundpoint is in the range of previous chunk + auto const &previouschunkdata{ m_soundchunks[ chunkindex - 1 ].second }; + m_properties.pitch = + interpolate( + previouschunkdata.pitch / chunkdata.pitch, + 1.f, + clamp( + ( soundpoint - previouschunkdata.threshold ) / ( chunkdata.threshold - previouschunkdata.threshold ), + 0.f, 1.f ) ); + } } else { @@ -721,6 +724,13 @@ sound_source::is_playing( bool const Includesoundends ) const { return isplaying; } +// returns true if the source uses sample table +bool +sound_source::is_combined() const { + + return ( ( !m_soundchunks.empty() ) && ( sound( sound_id::main ).buffer == null_handle ) ); +} + // returns location of the sound source in simulation region space glm::dvec3 const sound_source::location() const { @@ -756,15 +766,14 @@ float const EU07_SOUNDPROOFING_NONE { 1.f }; bool sound_source::update_soundproofing() { - - // NOTE, HACK: current cab id can vary from -1 to +1 - // we use this as modifier to force re-calculations when moving between compartments + // NOTE, HACK: current cab id can vary from -1 to +1, and we use another higher priority value for open cab window + // we use this as modifier to force re-calculations when moving between compartments or changing window state int const activecab = ( - FreeFlyModeFlag ? - 0 : - ( Global::pWorld->train() ? - Global::pWorld->train()->Dynamic()->MoverParameters->ActiveCab : - 0 ) ); + Global::CabWindowOpen ? 2 : + FreeFlyModeFlag ? 0 : + ( Global::pWorld->train() ? + Global::pWorld->train()->Dynamic()->MoverParameters->ActiveCab : + 0 ) ); // location-based gain factor: std::uintptr_t soundproofingstamp = reinterpret_cast( ( FreeFlyModeFlag ? @@ -784,15 +793,15 @@ sound_source::update_soundproofing() { } case sound_placement::external: { m_properties.soundproofing = ( - soundproofingstamp == 0 ? - EU07_SOUNDPROOFING_NONE : // listener outside - EU07_SOUNDPROOFING_STRONG ); // listener in a vehicle + ( ( soundproofingstamp == 0 ) || ( true == Global::CabWindowOpen ) ) ? + EU07_SOUNDPROOFING_NONE : // listener outside or has a window open + EU07_SOUNDPROOFING_STRONG ); // listener in a vehicle with windows shut break; } case sound_placement::internal: { m_properties.soundproofing = ( soundproofingstamp == 0 ? - EU07_SOUNDPROOFING_STRONG : // listener outside + EU07_SOUNDPROOFING_STRONG : // listener outside HACK: won't be true if active vehicle has open window ( Global::pWorld->train()->Dynamic() != m_owner ? EU07_SOUNDPROOFING_STRONG : // in another vehicle ( activecab == 0 ? @@ -802,13 +811,13 @@ sound_source::update_soundproofing() { } case sound_placement::engine: { m_properties.soundproofing = ( - soundproofingstamp == 0 ? - EU07_SOUNDPROOFING_SOME : // listener outside - ( Global::pWorld->train()->Dynamic() != m_owner ? - EU07_SOUNDPROOFING_STRONG : // in another vehicle - ( activecab == 0 ? - EU07_SOUNDPROOFING_NONE : // listener in the engine compartment - EU07_SOUNDPROOFING_STRONG ) ) ); // listener in another compartment of the same vehicle + ( ( soundproofingstamp == 0 ) || ( true == Global::CabWindowOpen ) ) ? + EU07_SOUNDPROOFING_SOME : // listener outside or has a window open + ( Global::pWorld->train()->Dynamic() != m_owner ? + EU07_SOUNDPROOFING_STRONG : // in another vehicle + ( activecab == 0 ? + EU07_SOUNDPROOFING_NONE : // listener in the engine compartment + EU07_SOUNDPROOFING_STRONG ) ) ); // listener in another compartment of the same vehicle break; } default: { diff --git a/sound.h b/sound.h index cc870889..08bed00a 100644 --- a/sound.h +++ b/sound.h @@ -97,6 +97,9 @@ public: // returns true if the source is emitting any sound; by default doesn't take into account optional ending soudnds bool is_playing( bool const Includesoundends = false ) const; + // returns true if the source uses sample table + bool + is_combined() const; // returns location of the sound source in simulation region space glm::dvec3 const location() const; diff --git a/version.h b/version.h index fa045cb1..0b6c16aa 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 17 -#define VERSION_MINOR 1205 +#define VERSION_MINOR 1214 #define VERSION_REVISION 0