diff --git a/Camera.cpp b/Camera.cpp index 6b62ed67..4fc6d388 100644 --- a/Camera.cpp +++ b/Camera.cpp @@ -51,7 +51,7 @@ bool TCamera::OnCommand( command_data const &Command ) { auto const walkspeed { 1.0 }; - auto const runspeed { 7.5 }; + auto const runspeed { 10.0 }; bool iscameracommand { true }; switch( Command.command ) { @@ -158,9 +158,9 @@ void TCamera::Update() || ( true == DebugCameraFlag ) ) { // ctrl is used for mirror view, so we ignore the controls when in vehicle if ctrl is pressed // McZapkie-170402: poruszanie i rozgladanie we free takie samo jak w follow - Velocity.x = clamp( Velocity.x + m_moverate.x * 10.0 * deltatime, -m_moverate.x, m_moverate.x ); - Velocity.z = clamp( Velocity.z + m_moverate.z * 10.0 * deltatime, -m_moverate.z, m_moverate.z ); - Velocity.y = clamp( Velocity.y + m_moverate.y * 10.0 * deltatime, -m_moverate.y, m_moverate.y ); + Velocity.x = clamp( Velocity.x + m_moverate.x * 10.0 * deltatime, -std::abs( m_moverate.x ), std::abs( m_moverate.x ) ); + Velocity.z = clamp( Velocity.z + m_moverate.z * 10.0 * deltatime, -std::abs( m_moverate.z ), std::abs( m_moverate.z ) ); + Velocity.y = clamp( Velocity.y + m_moverate.y * 10.0 * deltatime, -std::abs( m_moverate.y ), std::abs( m_moverate.y ) ); } if( ( Type == tp_Free ) diff --git a/DynObj.cpp b/DynObj.cpp index 4847bacc..ef07170b 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -3608,13 +3608,14 @@ void TDynamicObject::RenderSounds() { } // McZapkie-280302 - pisk mocno zacisnietych hamulcow - if( //( false == MoverParameters->SlippingWheels ) && - ( MoverParameters->UnitBrakeForce > rsPisk.m_amplitudefactor ) - && ( MoverParameters->Vel > 2.5 ) ) { + if( MoverParameters->Vel > 2.5 ) { - rsPisk - .gain( MoverParameters->UnitBrakeForce / ( rsPisk.m_amplitudefactor + 1 ) + rsPisk.m_amplitudeoffset ) - .play( sound_flags::exclusive | sound_flags::looping ); + volume = rsPisk.m_amplitudeoffset + interpolate( -1.0, 1.0, brakeforceratio ) * rsPisk.m_amplitudefactor; + if( volume > 0.075 ) { + rsPisk + .gain( volume ) + .play( sound_flags::exclusive | sound_flags::looping ); + } } else { // don't stop the sound too abruptly @@ -3769,24 +3770,6 @@ void TDynamicObject::RenderSounds() { // McZapkie! - to wazne - SoundFlag wystawiane jest przez moje moduly // gdy zachodza pewne wydarzenia komentowane dzwiekiem. - if( TestFlag( MoverParameters->SoundFlag, sound::relay ) ) { - // przekaznik - gdy bezpiecznik, automatyczny rozruch itp - if( true == TestFlag( MoverParameters->SoundFlag, sound::parallel ) ) { - if( TestFlag( MoverParameters->SoundFlag, sound::loud ) ) - m_powertrainsounds.dsbWejscie_na_bezoporow.play(); - else - m_powertrainsounds.motor_parallel.play(); - } - else { - m_powertrainsounds.motor_relay - .gain( - true == TestFlag( MoverParameters->SoundFlag, sound::loud ) ? - 1.0f : - 0.8f ) - .play(); - } - } - if( TestFlag( MoverParameters->SoundFlag, sound::pneumatic ) ) { // pneumatic relay dsbPneumaticRelay @@ -3796,7 +3779,6 @@ void TDynamicObject::RenderSounds() { 0.8f ) .play(); } - // couplers int couplerindex { 0 }; for( auto &couplersounds : m_couplersounds ) { @@ -4642,6 +4624,11 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, rsPisk.deserialize( parser, sound_type::single, sound_parameters::range | sound_parameters::amplitude ); rsPisk.owner( this ); + if( rsPisk.m_amplitudefactor > 10.f ) { + // HACK: convert old style activation point threshold to the new, regular amplitude adjustment system + rsPisk.m_amplitudefactor = 1.f; + rsPisk.m_amplitudeoffset = 0.f; + } rsPisk.m_amplitudeoffset *= ( 105.f - Random( 10.f ) ) / 100.f; } @@ -4821,10 +4808,10 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, m_powertrainsounds.motor_relay.deserialize( parser, sound_type::single ); m_powertrainsounds.motor_relay.owner( this ); } - else if( token == "pneumaticrelay:" ) { - // wylaczniki pneumatyczne: - dsbPneumaticRelay.deserialize( parser, sound_type::single ); - dsbPneumaticRelay.owner( this ); + else if( token == "shuntfield:" ) { + // styczniki itp: + m_powertrainsounds.motor_shuntfield.deserialize( parser, sound_type::single ); + m_powertrainsounds.motor_shuntfield.owner( this ); } else if( token == "wejscie_na_bezoporow:" ) { // hunter-111211: wydzielenie wejscia na bezoporowa i na drugi uklad do pliku @@ -4835,6 +4822,11 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, m_powertrainsounds.motor_parallel.deserialize( parser, sound_type::single ); m_powertrainsounds.motor_parallel.owner( this ); } + else if( token == "pneumaticrelay:" ) { + // wylaczniki pneumatyczne: + dsbPneumaticRelay.deserialize( parser, sound_type::single ); + dsbPneumaticRelay.owner( this ); + } // braking sounds else if( token == "brakesound:" ) { // hamowanie zwykle: @@ -5778,6 +5770,50 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub motor.stop(); } + auto const soundflags { Vehicle.SoundFlag }; + if( TestFlag( soundflags, sound::relay ) ) { + // przekaznik - gdy bezpiecznik, automatyczny rozruch itp + if( true == TestFlag( soundflags, sound::shuntfield ) ) { + // shunt field + motor_shuntfield + .pitch( + true == motor_shuntfield.is_combined() ? + Vehicle.ScndCtrlActualPos * 0.01f : + motor_shuntfield.m_frequencyoffset + 1.f * motor_shuntfield.m_frequencyfactor ) + .gain( + motor_shuntfield.m_amplitudeoffset + ( + true == TestFlag( soundflags, sound::loud ) ? + 1.0f : + 0.8f ) + * motor_shuntfield.m_amplitudefactor ) + .play(); + } + else if( true == TestFlag( soundflags, sound::parallel ) ) { + // parallel mode + if( TestFlag( soundflags, sound::loud ) ) { + dsbWejscie_na_bezoporow.play(); + } + else { + motor_parallel.play(); + } + } + else { + // series mode + motor_relay + .pitch( + true == motor_relay.is_combined() ? + Vehicle.MainCtrlActualPos * 0.01f : + motor_relay.m_frequencyoffset + 1.f * motor_relay.m_frequencyfactor ) + .gain( + motor_relay.m_amplitudeoffset + ( + true == TestFlag( soundflags, sound::loud ) ? + 1.0f : + 0.8f ) + * motor_relay.m_amplitudefactor ) + .play(); + } + } + if( ( Vehicle.EngineType == ElectricSeriesMotor ) || ( Vehicle.EngineType == ElectricInductionMotor ) ) { @@ -5799,7 +5835,6 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub } } - if( Vehicle.TrainType == dt_ET40 ) { if( Vehicle.Vel > 0.1 ) { transmission diff --git a/DynObj.h b/DynObj.h index c0cf4367..16c644c2 100644 --- a/DynObj.h +++ b/DynObj.h @@ -290,6 +290,7 @@ private: sound_source motor_relay { sound_placement::engine }; sound_source dsbWejscie_na_bezoporow { sound_placement::engine }; // moved from cab sound_source motor_parallel { sound_placement::engine }; // moved from cab + sound_source motor_shuntfield { sound_placement::engine }; sound_source rsWentylator { sound_placement::engine }; // McZapkie-030302 sound_source engine { sound_placement::engine }; // generally diesel engine sound_source engine_ignition { sound_placement::engine }; // moved from cab diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 5d1f2048..8dd8e9ff 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -204,7 +204,8 @@ enum sound { bufferclash = 0x4, relay = 0x10, parallel = 0x20, - pneumatic = 0x40 + shuntfield = 0x40, + pneumatic = 0x80 }; //szczególne typy pojazdów (inna obsługa) dla zmiennej TrainType diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index ded32795..76cbd3c6 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -4622,24 +4622,19 @@ double TMoverParameters::TractionForce(double dt) { if( ( ScndCtrlPos < ScndCtrlPosNo ) && ( MainCtrlPos >= 10 ) ) { - if( ScndCtrlPos == 0 ) { - if( Im < MPTRelay[ ScndCtrlPos ].Iup ) { - ++ScndCtrlPos; - } + + if( Im < MPTRelay[ ScndCtrlPos ].Iup ) { + ++ScndCtrlPos; } - else { - if( Vel > MPTRelay[ ScndCtrlPos ].Iup ) { - ++ScndCtrlPos; - } - // check for cases where the speed drops below threshold for level 2 or 3 - if( ( ScndCtrlPos > 1 ) - && ( Vel < MPTRelay[ ScndCtrlPos - 1 ].Idown ) ) { - --ScndCtrlPos; - } + // check for cases where the speed drops below threshold for level 2 or 3 + if( ( ScndCtrlPos > 1 ) + && ( Vel < MPTRelay[ ScndCtrlPos - 1 ].Idown ) ) { + --ScndCtrlPos; } } // malenie if( ( ScndCtrlPos > 0 ) && ( MainCtrlPos < 10 ) ) { + if( ScndCtrlPos == 1 ) { if( Im > MPTRelay[ ScndCtrlPos - 1 ].Idown ) { --ScndCtrlPos; @@ -4659,6 +4654,13 @@ double TMoverParameters::TractionForce(double dt) if( MainCtrlPos < 7 ) { ScndCtrlPos = 0; } +/* + // crude woodward approximation; difference between rpm for consecutive positions is ~5% + // so we get full throttle until ~half way between desired and previous position, or zero on rpm reduction + auto const woodward { clamp( + ( DElist[ MainCtrlPos ].RPM / ( enrot * 60.0 ) - 1.0 ) * 50.0, + 0.0, 1.0 ) }; +*/ break; } case 46: @@ -5224,7 +5226,8 @@ bool TMoverParameters::AutoRelayCheck(void) { if ((LastRelayTime > CtrlDelay) && (ARFASI2)) { - ScndCtrlActualPos++; + ++ScndCtrlActualPos; + SetFlag( SoundFlag, sound::shuntfield ); OK = true; } } @@ -5232,7 +5235,8 @@ bool TMoverParameters::AutoRelayCheck(void) { if ((LastRelayTime > CtrlDownDelay) && (TrainType != dt_EZT)) { - ScndCtrlActualPos--; + --ScndCtrlActualPos; + SetFlag( SoundFlag, sound::shuntfield ); OK = true; } } @@ -5260,7 +5264,7 @@ bool TMoverParameters::AutoRelayCheck(void) && ( MainCtrlPos != MainCtrlPosNo ) && ( FastSerialCircuit == 1 ) ) { - MainCtrlActualPos++; + ++MainCtrlActualPos; // MainCtrlActualPos:=MainCtrlPos; //hunter-111012: // szybkie wchodzenie na bezoporowa (303E) OK = true; @@ -5275,7 +5279,7 @@ bool TMoverParameters::AutoRelayCheck(void) (DelayCtrlFlag))) // et22 z walem grupowym if (!DelayCtrlFlag) // najpierw przejscie { - MainCtrlActualPos++; + ++MainCtrlActualPos; DelayCtrlFlag = true; // tryb przejscia OK = true; } @@ -5289,7 +5293,7 @@ bool TMoverParameters::AutoRelayCheck(void) ; else // nie ET22 z wałem grupowym { - MainCtrlActualPos++; + ++MainCtrlActualPos; OK = true; } //--------- @@ -5313,7 +5317,7 @@ bool TMoverParameters::AutoRelayCheck(void) if ((RList[MainCtrlPos].R == 0) && (MainCtrlPos > 0) && (!(MainCtrlPos == MainCtrlPosNo)) && (FastSerialCircuit == 1)) { - MainCtrlActualPos--; + --MainCtrlActualPos; // MainCtrlActualPos:=MainCtrlPos; //hunter-111012: // szybkie wchodzenie na bezoporowa (303E) OK = true; @@ -5323,13 +5327,12 @@ bool TMoverParameters::AutoRelayCheck(void) { if (TrainType != dt_EZT) // tutaj powinien być tryb sterowania wałem { - MainCtrlActualPos--; + --MainCtrlActualPos; OK = true; } if (MainCtrlActualPos > 0) // hunter-111211: poprawki - if (RList[MainCtrlActualPos].R == - 0) // dzwieki schodzenia z bezoporowej} - { + if (RList[MainCtrlActualPos].R == 0) { + // dzwieki schodzenia z bezoporowej} SetFlag(SoundFlag, sound::parallel); } } @@ -5338,7 +5341,8 @@ bool TMoverParameters::AutoRelayCheck(void) { if (LastRelayTime > CtrlDownDelay) { - ScndCtrlActualPos--; // boczniki nie dzialaja na poz. oporowych + --ScndCtrlActualPos; // boczniki nie dzialaja na poz. oporowych + SetFlag( SoundFlag, sound::shuntfield ); OK = true; } } @@ -5369,45 +5373,61 @@ bool TMoverParameters::AutoRelayCheck(void) else DelayCtrlFlag = false; - if ((!StLinFlag) && ((MainCtrlActualPos > 0) || (ScndCtrlActualPos > 0))) - if ((TrainType == dt_EZT) && (CoupledCtrl)) // EN57 wal jednokierunkowy calosciowy - { - if (MainCtrlActualPos == 1) - { - MainCtrlActualPos = 0; - OK = true; - } - else if (LastRelayTime > CtrlDownDelay) - { - if (MainCtrlActualPos < RlistSize) - MainCtrlActualPos++; // dojdz do konca - else if (ScndCtrlActualPos < ScndCtrlPosNo) - ScndCtrlActualPos++; // potem boki - else - { // i sie przewroc na koniec + if( ( false == StLinFlag ) + && ( ( MainCtrlActualPos > 0 ) + || ( ScndCtrlActualPos > 0 ) ) ) { + + if( true == CoupledCtrl ) { + + if( TrainType == dt_EZT ) { + // EN57 wal jednokierunkowy calosciowy + if( MainCtrlActualPos == 1 ) { + MainCtrlActualPos = 0; - ScndCtrlActualPos = 0; + OK = true; + } + else { + + if( LastRelayTime > CtrlDownDelay ) { + + if( MainCtrlActualPos < RlistSize ) { + // dojdz do konca + ++MainCtrlActualPos; + } + else if( ScndCtrlActualPos < ScndCtrlPosNo ) { + // potem boki + ++ScndCtrlActualPos; + SetFlag( SoundFlag, sound::shuntfield ); + } + else { + // i sie przewroc na koniec + MainCtrlActualPos = 0; + ScndCtrlActualPos = 0; + } + OK = true; + } + } + } + else { + // wal kulakowy dwukierunkowy + if( LastRelayTime > CtrlDownDelay ) { + if( ScndCtrlActualPos > 0 ) { + --ScndCtrlActualPos; + SetFlag( SoundFlag, sound::shuntfield ); + } + else { + --MainCtrlActualPos; + } + OK = true; } - OK = true; } } - else if (CoupledCtrl) // wal kulakowy dwukierunkowy - { - if (LastRelayTime > CtrlDownDelay) - { - if (ScndCtrlActualPos > 0) - ScndCtrlActualPos--; - else - MainCtrlActualPos--; - OK = true; - } - } - else - { + else { MainCtrlActualPos = 0; ScndCtrlActualPos = 0; OK = true; } + } } if (OK) LastRelayTime = 0; diff --git a/sound.cpp b/sound.cpp index 9f768644..c101e1d9 100644 --- a/sound.cpp +++ b/sound.cpp @@ -57,14 +57,30 @@ sound_source::deserialize( cParser &Input, sound_type const Legacytype, int cons // on the far end the crossfade section extends to the threshold point of the next chunk... for( std::size_t idx = 0; idx < m_soundchunks.size() - 1; ++idx ) { m_soundchunks[ idx ].second.fadeout = m_soundchunks[ idx + 1 ].second.threshold; +/* + m_soundchunks[ idx ].second.fadeout = + interpolate( + m_soundchunks[ idx ].second.threshold, + m_soundchunks[ idx + 1 ].second.threshold, + m_crossfaderange * 0.01f ); +*/ } // ...and on the other end from the threshold point back into the range of previous chunk m_soundchunks.front().second.fadein = std::max( 0, m_soundchunks.front().second.threshold ); +// m_soundchunks.front().second.fadein = m_soundchunks.front().second.threshold; for( std::size_t idx = 1; idx < m_soundchunks.size(); ++idx ) { auto const previouschunkwidth { m_soundchunks[ idx ].second.threshold - m_soundchunks[ idx - 1 ].second.threshold }; m_soundchunks[ idx ].second.fadein = m_soundchunks[ idx ].second.threshold - 0.01f * m_crossfaderange * previouschunkwidth; +/* + m_soundchunks[ idx ].second.fadein = + interpolate( + m_soundchunks[ idx ].second.threshold, + m_soundchunks[ idx - 1 ].second.threshold, + m_crossfaderange * 0.01f ); +*/ } m_soundchunks.back().second.fadeout = std::max( 100, m_soundchunks.back().second.threshold ); +// m_soundchunks.back().second.fadeout = m_soundchunks.back().second.threshold; // test if the chunk table contains any actual samples while at it for( auto &soundchunk : m_soundchunks ) { if( soundchunk.first.buffer != null_handle ) { @@ -353,7 +369,7 @@ sound_source::play_combined() { // a chunk covers range from fade in point, where it starts rising in volume over crossfade distance, // lasts until fadeout - crossfade distance point, past which it grows quiet until fade out point where it ends if( soundpoint < soundchunk.second.fadein ) { break; } - if( soundpoint > soundchunk.second.fadeout ) { continue; } + if( soundpoint >= soundchunk.second.fadeout ) { continue; } if( ( soundchunk.first.playing > 0 ) || ( soundchunk.first.buffer == null_handle ) ) { @@ -564,7 +580,7 @@ sound_source::update_combined( audio::openal_source &Source ) { auto const soundpoint { compute_combined_point() }; auto const &soundchunk { m_soundchunks[ soundhandle ^ sound_id::chunk ] }; if( ( soundpoint < soundchunk.second.fadein ) - || ( soundpoint > soundchunk.second.fadeout ) ) { + || ( soundpoint >= soundchunk.second.fadeout ) ) { Source.stop(); update_counter( soundhandle, -1 ); return; @@ -681,7 +697,6 @@ sound_source::update_crossfade( sound_handle const Chunk ) { m_properties.pitch = 1.f; } } - // if there's no crossfade sections, our work is done if( m_crossfaderange == 0 ) { return; } diff --git a/version.h b/version.h index e1eaf929..2a1f3bf1 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once -#define VERSION_MAJOR 17 -#define VERSION_MINOR 1231 +#define VERSION_MAJOR 18 +#define VERSION_MINOR 113 #define VERSION_REVISION 0