16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-22 20:59:19 +02:00

build 210508. spring brake sound support, internaldata sounds update fix, minor bug fixes

This commit is contained in:
tmj-fstate
2021-05-09 02:01:16 +02:00
parent fa9136e333
commit 51415ef71f
8 changed files with 494 additions and 543 deletions

View File

@@ -2709,10 +2709,11 @@ bool TController::PrepareEngine()
cue_action( locale::string::driver_hint_pantographcompressoroff ); // sprężarkę pantografów można już wyłączyć cue_action( locale::string::driver_hint_pantographcompressoroff ); // sprężarkę pantografów można już wyłączyć
} }
} }
// TODO: make pantograph setup a part of control_pantographs() and call it here instead
if( ( fOverhead2 == -1.0 ) && ( iOverheadDown == 0 ) ) { if( ( fOverhead2 == -1.0 ) && ( iOverheadDown == 0 ) ) {
cue_action( locale::string::driver_hint_pantographsvalveon ); cue_action( locale::string::driver_hint_pantographsvalveon );
cue_action( locale::string::driver_hint_frontpantographvalveon ); cue_action( locale::string::driver_hint_frontpantographvalveon, ( iDirection >= 0 ? 5 : 0 ) );
cue_action( locale::string::driver_hint_rearpantographvalveon ); cue_action( locale::string::driver_hint_rearpantographvalveon, ( iDirection >= 0 ? 0 : 5 ) );
} }
} }

View File

@@ -4209,7 +4209,7 @@ void TDynamicObject::RenderSounds() {
} }
// Dzwiek odluzniacza // Dzwiek odluzniacza
if( MoverParameters->Hamulec->GetStatus() & b_rls ) { if( MoverParameters->Hamulec->Releaser() ) {
sReleaser sReleaser
.gain( .gain(
clamp<float>( clamp<float>(
@@ -4294,6 +4294,19 @@ void TDynamicObject::RenderSounds() {
rsPisk.stop(); rsPisk.stop();
} }
// spring brake
if( m_springbrakesounds.state != MoverParameters->SpringBrake.Activate ) {
m_springbrakesounds.state = MoverParameters->SpringBrake.Activate;
if( m_springbrakesounds.state ) {
m_springbrakesounds.activate.play( sound_flags::exclusive );
m_springbrakesounds.release.stop();
}
else {
m_springbrakesounds.activate.stop();
m_springbrakesounds.release.play( sound_flags::exclusive );
}
}
// other sounds // other sounds
// load exchange // load exchange
if( MoverParameters->LoadStatus & 1 ) { if( MoverParameters->LoadStatus & 1 ) {
@@ -5702,6 +5715,15 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
rsUnbrake.deserialize( parser, sound_type::single, sound_parameters::range ); rsUnbrake.deserialize( parser, sound_type::single, sound_parameters::range );
rsUnbrake.owner( this ); rsUnbrake.owner( this );
} }
// spring brake sounds
else if( token == "springbrake:" ) {
m_springbrakesounds.activate.deserialize( parser, sound_type::single );
m_springbrakesounds.activate.owner( this );
}
else if( token == "springbrakeoff:" ) {
m_springbrakesounds.release.deserialize( parser, sound_type::single );
m_springbrakesounds.release.owner( this );
}
else if( token == "derail:" ) { else if( token == "derail:" ) {
// dzwiek przy wykolejeniu // dzwiek przy wykolejeniu

View File

@@ -421,6 +421,12 @@ private:
sound_source announcement; sound_source announcement;
std::deque<sound_source> announcement_queue; // fifo queue std::deque<sound_source> announcement_queue; // fifo queue
}; };
struct springbrake_sounds {
sound_source activate { sound_placement::external };
sound_source release { sound_placement::external };
bool state { false };
};
// methods // methods
void ABuLittleUpdate(double ObjSqrDist); void ABuLittleUpdate(double ObjSqrDist);
@@ -496,6 +502,7 @@ private:
sound_source m_emergencybrake { sound_placement::engine }; sound_source m_emergencybrake { sound_placement::engine };
double m_emergencybrakeflow{ 0.f }; double m_emergencybrakeflow{ 0.f };
sound_source sReleaser { sound_placement::external }; sound_source sReleaser { sound_placement::external };
springbrake_sounds m_springbrakesounds;
sound_source rsSlippery { sound_placement::external, EU07_SOUND_BRAKINGCUTOFFRANGE }; // moved from cab sound_source rsSlippery { sound_placement::external, EU07_SOUND_BRAKINGCUTOFFRANGE }; // moved from cab
sound_source sSand { sound_placement::external }; sound_source sSand { sound_placement::external };
// moving part and other external sounds // moving part and other external sounds

View File

@@ -286,25 +286,25 @@ TGauge::Load_mapping( cParser &Input, TGauge::scratch_data &Scratchpad ) {
return true; // return value marks a key: value pair was extracted, nothing about whether it's recognized return true; // return value marks a key: value pair was extracted, nothing about whether it's recognized
} }
void
TGauge::UpdateValue( float fNewDesired ) {
return UpdateValue( fNewDesired, nullptr );
}
void
TGauge::UpdateValue( float fNewDesired, sound_source &Fallbacksound ) {
return UpdateValue( fNewDesired, &Fallbacksound );
}
// ustawienie wartości docelowej. plays provided fallback sound, if no sound was defined in the control itself // ustawienie wartości docelowej. plays provided fallback sound, if no sound was defined in the control itself
void bool
TGauge::UpdateValue( float fNewDesired, sound_source *Fallbacksound ) { TGauge::UpdateValue( float fNewDesired, std::optional<sound_source> &Fallbacksound ) {
if( false == UpdateValue( fNewDesired ) ) {
if( Fallbacksound ) {
Fallbacksound->play( m_soundtype );
return true;
}
}
return false;
}
bool
TGauge::UpdateValue( float fNewDesired ) {
auto const desiredtimes100 = static_cast<int>( std::round( 100.0 * fNewDesired ) ); auto const desiredtimes100 = static_cast<int>( std::round( 100.0 * fNewDesired ) );
if( desiredtimes100 == static_cast<int>( std::round( 100.0 * m_targetvalue ) ) ) { if( desiredtimes100 == static_cast<int>( std::round( 100.0 * m_targetvalue ) ) ) {
return; return true;
} }
m_targetvalue = fNewDesired; m_targetvalue = fNewDesired;
// if there's any sound associated with new requested value, play it // if there's any sound associated with new requested value, play it
@@ -315,7 +315,7 @@ TGauge::UpdateValue( float fNewDesired, sound_source *Fallbacksound ) {
auto const lookup = m_soundfxvalues.find( desiredtimes100 / 100 ); auto const lookup = m_soundfxvalues.find( desiredtimes100 / 100 );
if( lookup != m_soundfxvalues.end() ) { if( lookup != m_soundfxvalues.end() ) {
lookup->second.play(); lookup->second.play();
return; return true;
} }
} }
else { else {
@@ -329,20 +329,17 @@ TGauge::UpdateValue( float fNewDesired, sound_source *Fallbacksound ) {
// shift up // shift up
if( false == m_soundfxincrease.empty() ) { if( false == m_soundfxincrease.empty() ) {
m_soundfxincrease.play( m_soundtype ); m_soundfxincrease.play( m_soundtype );
return; return true;
} }
} }
else if( currentvalue > fNewDesired ) { else if( currentvalue > fNewDesired ) {
// shift down // shift down
if( false == m_soundfxdecrease.empty() ) { if( false == m_soundfxdecrease.empty() ) {
m_soundfxdecrease.play( m_soundtype ); m_soundfxdecrease.play( m_soundtype );
return; return true;
} }
} }
if( Fallbacksound != nullptr ) { return false; // no suitable sound was found
// ...and if that fails too, try the provided fallback sound from legacy system
Fallbacksound->play( m_soundtype );
}
}; };
void TGauge::PutValue(float fNewDesired) void TGauge::PutValue(float fNewDesired)

View File

@@ -43,8 +43,8 @@ public:
*this = TGauge(); } *this = TGauge(); }
void Init(TSubModel *Submodel, TSubModel *Submodelon, TGaugeAnimation Type, float Scale = 1, float Offset = 0, float Friction = 0, float Value = 0, float const Endvalue = -1.0, float const Endscale = -1.0, bool const Interpolate = false ); void Init(TSubModel *Submodel, TSubModel *Submodelon, TGaugeAnimation Type, float Scale = 1, float Offset = 0, float Friction = 0, float Value = 0, float const Endvalue = -1.0, float const Endscale = -1.0, bool const Interpolate = false );
void Load(cParser &Parser, TDynamicObject const *Owner, double const mul = 1.0); void Load(cParser &Parser, TDynamicObject const *Owner, double const mul = 1.0);
void UpdateValue( float fNewDesired ); bool UpdateValue( float fNewDesired );
void UpdateValue( float fNewDesired, sound_source &Fallbacksound ); bool UpdateValue( float fNewDesired, std::optional<sound_source> &Fallbacksound );
void PutValue(float fNewDesired); void PutValue(float fNewDesired);
float GetValue() const; float GetValue() const;
float GetDesiredValue() const; float GetDesiredValue() const;
@@ -79,8 +79,6 @@ private:
// imports member data pair from the config file // imports member data pair from the config file
bool bool
Load_mapping( cParser &Input, TGauge::scratch_data &Scratchpad ); Load_mapping( cParser &Input, TGauge::scratch_data &Scratchpad );
void
UpdateValue( float fNewDesired, sound_source *Fallbacksound );
float float
GetScaledValue() const; GetScaledValue() const;
void void

652
Train.cpp
View File

@@ -671,32 +671,33 @@ dictionary_source *TTrain::GetTrainState( dictionary_source const &Extraparamete
for( int j = 0; j < 10; ++j ) for( int j = 0; j < 10; ++j )
dict->insert( ( "eimp_t_" + std::string( TXTT[ j ] ) ), fEIMParams[ 0 ][ j ] ); dict->insert( ( "eimp_t_" + std::string( TXTT[ j ] ) ), fEIMParams[ 0 ][ j ] );
for( int i = 0; i < 8; ++i ) { for( int i = 0; i < 8; ++i ) {
auto const idx { std::to_string( i + 1 ) };
for( int j = 0; j < 10; ++j ) for( int j = 0; j < 10; ++j )
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_" + std::string( TXTC[ j ] ) ), fEIMParams[ i + 1 ][ j ] ); dict->insert( ( "eimp_c" + idx + "_" + std::string( TXTC[ j ] ) ), fEIMParams[ i + 1 ][ j ] );
for (int j = 0; j < 10; ++j) for (int j = 0; j < 10; ++j)
dict->insert(("diesel_param_" + std::to_string(i + 1) + "_" + std::string(TXTD[j])), fDieselParams[i + 1][j]); dict->insert(("diesel_param_" + idx + "_" + std::string(TXTD[j])), fDieselParams[i + 1][j]);
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_ms" ), bMains[ i ] ); dict->insert( ( "eimp_c" + idx + "_ms" ), bMains[ i ] );
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_cv" ), fCntVol[ i ] ); dict->insert( ( "eimp_c" + idx + "_cv" ), fCntVol[ i ] );
dict->insert( ( "eimp_u" + std::to_string( i + 1 ) + "_pf" ), bPants[ i ][ 0 ] ); dict->insert( ( "eimp_c" + idx + "_fuse" ), bFuse[ i ] );
dict->insert( ( "eimp_u" + std::to_string( i + 1 ) + "_pr" ), bPants[ i ][ 1 ] ); dict->insert( ( "eimp_c" + idx + "_batt" ), bBatt[ i ] );
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_fuse" ), bFuse[ i ] ); dict->insert( ( "eimp_c" + idx + "_conv" ), bConv[ i ] );
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_batt" ), bBatt[ i ] ); dict->insert( ( "eimp_c" + idx + "_heat" ), bHeat[ i ] );
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_conv" ), bConv[ i ] );
dict->insert( ( "eimp_u" + std::to_string( i + 1 ) + "_comp_a" ), bComp[ i ][ 0 ] ); dict->insert( ( "eimp_u" + idx + "_pf" ), bPants[ i ][ 0 ] );
dict->insert( ( "eimp_u" + std::to_string( i + 1 ) + "_comp_w" ), bComp[ i ][ 1 ] ); dict->insert( ( "eimp_u" + idx + "_pr" ), bPants[ i ][ 1 ] );
//dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_comp_a" ), bComp[ i ][ 2 ]); dict->insert( ( "eimp_u" + idx + "_comp_a" ), bComp[ i ][ 0 ] );
//dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_comp_w" ), bComp[ i ][ 3 ]); dict->insert( ( "eimp_u" + idx + "_comp_w" ), bComp[ i ][ 1 ] );
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_heat" ), bHeat[ i ] );
} }
dict->insert( "compressors_no", (int)bCompressors.size() ); dict->insert( "compressors_no", (int)bCompressors.size() );
for (int i = 0; i < bCompressors.size(); i++) for (int i = 0; i < bCompressors.size(); i++)
{ {
dict->insert("compressors_" + std::to_string(i + 1) + "_allow", std::get<0>(bCompressors[i])); auto const idx { std::to_string( i + 1 ) };
dict->insert("compressors_" + std::to_string(i + 1) + "_work", std::get<1>(bCompressors[i])); dict->insert("compressors_" + idx + "_allow", std::get<0>(bCompressors[i]));
dict->insert("compressors_" + std::to_string(i + 1) + "_car_no", std::get<2>(bCompressors[i])); dict->insert("compressors_" + idx + "_work", std::get<1>(bCompressors[i]));
dict->insert("compressors_" + idx + "_car_no", std::get<2>(bCompressors[i]));
} }
@@ -856,7 +857,9 @@ void TTrain::set_train_brake( double const Position ) {
( ( originalbrakeposition / 100 == 0 ) || ( originalbrakeposition / 100 >= 5 ) ) ( ( originalbrakeposition / 100 == 0 ) || ( originalbrakeposition / 100 >= 5 ) )
&& ( ( mvOccupied->BrakeCtrlPos == 0 ) || ( mvOccupied->BrakeCtrlPos >= 5 ) ) ) ) ) { && ( ( mvOccupied->BrakeCtrlPos == 0 ) || ( mvOccupied->BrakeCtrlPos >= 5 ) ) ) ) ) {
// sound feedback if the lever movement activates one of the switches // sound feedback if the lever movement activates one of the switches
dsbPneumaticSwitch.play(); if( dsbPneumaticSwitch ) {
dsbPneumaticSwitch->play();
}
} }
} }
@@ -1839,7 +1842,9 @@ void TTrain::OnCommand_epbrakecontroltoggle( TTrain *Train, command_data const &
// turn on // turn on
if( Train->mvOccupied->EpFuseSwitch( true ) ) { if( Train->mvOccupied->EpFuseSwitch( true ) ) {
// audio feedback // audio feedback
Train->dsbPneumaticSwitch.play(); if( Train->dsbPneumaticSwitch ) {
Train->dsbPneumaticSwitch->play();
}
}; };
} }
else { else {
@@ -1851,7 +1856,9 @@ void TTrain::OnCommand_epbrakecontroltoggle( TTrain *Train, command_data const &
// potentially turn on // potentially turn on
if( Train->mvOccupied->EpFuseSwitch( true ) ) { if( Train->mvOccupied->EpFuseSwitch( true ) ) {
// audio feedback // audio feedback
Train->dsbPneumaticSwitch.play(); if( Train->dsbPneumaticSwitch ) {
Train->dsbPneumaticSwitch->play();
}
}; };
} }
// visual feedback // visual feedback
@@ -6379,23 +6386,27 @@ bool TTrain::Update( double const Deltatime )
bPants[iUnitNo - 1][end::front] = ( bPants[iUnitNo - 1][end::front] || p->MoverParameters->Pantographs[end::front].is_active ); bPants[iUnitNo - 1][end::front] = ( bPants[iUnitNo - 1][end::front] || p->MoverParameters->Pantographs[end::front].is_active );
bPants[iUnitNo - 1][end::rear] = ( bPants[iUnitNo - 1][end::rear] || p->MoverParameters->Pantographs[end::rear].is_active ); bPants[iUnitNo - 1][end::rear] = ( bPants[iUnitNo - 1][end::rear] || p->MoverParameters->Pantographs[end::rear].is_active );
} }
// TBD, TODO: clean up compressor data arrangement?
if( iUnitNo <= 8 ) {
bComp[iUnitNo - 1][0] = (bComp[iUnitNo - 1][0] || p->MoverParameters->CompressorAllow || (p->MoverParameters->CompressorStart == start_t::automatic)); bComp[iUnitNo - 1][0] = (bComp[iUnitNo - 1][0] || p->MoverParameters->CompressorAllow || (p->MoverParameters->CompressorStart == start_t::automatic));
bSlip[i] = p->MoverParameters->SlippingWheels; }
if (p->MoverParameters->CompressorSpeed > 0.00001) if (p->MoverParameters->CompressorSpeed > 0.00001)
{ {
if( iUnitNo <= 8 ) {
bComp[iUnitNo - 1][1] = (bComp[iUnitNo - 1][1] || p->MoverParameters->CompressorFlag); bComp[iUnitNo - 1][1] = (bComp[iUnitNo - 1][1] || p->MoverParameters->CompressorFlag);
}
bCompressors.emplace_back( bCompressors.emplace_back(
p->MoverParameters->CompressorAllow || (p->MoverParameters->CompressorStart == start_t::automatic), p->MoverParameters->CompressorAllow || (p->MoverParameters->CompressorStart == start_t::automatic),
p->MoverParameters->CompressorFlag, p->MoverParameters->CompressorFlag,
i); i);
} }
bSlip[i] = p->MoverParameters->SlippingWheels;
if ((in < 8) && (p->MoverParameters->eimc[eimc_p_Pmax] > 1)) if ((in < 8) && (p->MoverParameters->eimc[eimc_p_Pmax] > 1))
{ {
fEIMParams[1 + in][0] = p->MoverParameters->eimv[eimv_Fmax]; fEIMParams[1 + in][0] = p->MoverParameters->eimv[eimv_Fmax];
fEIMParams[1 + in][1] = Max0R(fEIMParams[1 + in][0], 0); fEIMParams[1 + in][1] = Max0R(fEIMParams[1 + in][0], 0);
fEIMParams[1 + in][2] = -Min0R(fEIMParams[1 + in][0], 0); fEIMParams[1 + in][2] = -Min0R(fEIMParams[1 + in][0], 0);
fEIMParams[1 + in][3] = p->MoverParameters->eimv[eimv_Fmax] / fEIMParams[1 + in][3] = p->MoverParameters->eimv[eimv_Fmax] / Max0R(p->MoverParameters->eimv[eimv_Fful], 1);
Max0R(p->MoverParameters->eimv[eimv_Fful], 1);
fEIMParams[1 + in][4] = Max0R(fEIMParams[1 + in][3], 0); fEIMParams[1 + in][4] = Max0R(fEIMParams[1 + in][3], 0);
fEIMParams[1 + in][5] = -Min0R(fEIMParams[1 + in][3], 0); fEIMParams[1 + in][5] = -Min0R(fEIMParams[1 + in][3], 0);
fEIMParams[1 + in][6] = p->MoverParameters->eimv[eimv_If]; fEIMParams[1 + in][6] = p->MoverParameters->eimv[eimv_If];
@@ -6437,10 +6448,9 @@ bool TTrain::Update( double const Deltatime )
in++; in++;
iPowerNo = in; iPowerNo = in;
} }
// p = p->NextC(4); //prev if ((kier ? p->NextC(coupling::permanent) : p->PrevC(coupling::permanent)) != (kier ? p->NextC(coupling::control) : p->PrevC(coupling::control)))
if ((kier ? p->NextC(128) : p->PrevC(128)) != (kier ? p->NextC(4) : p->PrevC(4)))
iUnitNo++; iUnitNo++;
p = (kier ? p->NextC(4) : p->PrevC(4)); p = (kier ? p->NextC(coupling::control) : p->PrevC(coupling::control));
iCarNo = i + 1; iCarNo = i + 1;
} }
else else
@@ -7437,32 +7447,34 @@ TTrain::update_sounds( double const Deltatime ) {
} }
m_lastlocalbrakepressure = mvOccupied->LocBrakePress; m_lastlocalbrakepressure = mvOccupied->LocBrakePress;
// local brake, release // local brake, release
if( rsSBHiss ) {
if( ( m_localbrakepressurechange < -0.05f ) if( ( m_localbrakepressurechange < -0.05f )
&& ( mvOccupied->LocBrakePress > mvOccupied->BrakePress - 0.05 ) ) { && ( mvOccupied->LocBrakePress > mvOccupied->BrakePress - 0.05 ) ) {
rsSBHiss rsSBHiss->gain( clamp( rsSBHiss->m_amplitudeoffset + rsSBHiss->m_amplitudefactor * -m_localbrakepressurechange * 0.05, 0.0, 1.5 ) );
.gain( clamp( rsSBHiss.m_amplitudeoffset + rsSBHiss.m_amplitudefactor * -m_localbrakepressurechange * 0.05, 0.0, 1.5 ) ) rsSBHiss->play( sound_flags::exclusive | sound_flags::looping );
.play( sound_flags::exclusive | sound_flags::looping );
} }
else { else {
// don't stop the sound too abruptly // don't stop the sound too abruptly
volume = std::max( 0.0, rsSBHiss.gain() - 0.1 * Deltatime ); volume = std::max( 0.0, rsSBHiss->gain() - 0.1 * Deltatime );
rsSBHiss.gain( volume ); rsSBHiss->gain( volume );
if( volume < 0.05 ) { if( volume < 0.05 ) {
rsSBHiss.stop(); rsSBHiss->stop();
}
} }
} }
// local brake, engage // local brake, engage
if( rsSBHissU ) {
if( m_localbrakepressurechange > 0.05f ) { if( m_localbrakepressurechange > 0.05f ) {
rsSBHissU rsSBHissU->gain( clamp( rsSBHissU->m_amplitudeoffset + rsSBHissU->m_amplitudefactor * m_localbrakepressurechange * 0.05, 0.0, 1.5 ) );
.gain( clamp( rsSBHissU.m_amplitudeoffset + rsSBHissU.m_amplitudefactor * m_localbrakepressurechange * 0.05, 0.0, 1.5 ) ) rsSBHissU->play( sound_flags::exclusive | sound_flags::looping );
.play( sound_flags::exclusive | sound_flags::looping );
} }
else { else {
// don't stop the sound too abruptly // don't stop the sound too abruptly
volume = std::max( 0.0, rsSBHissU.gain() - 0.1 * Deltatime ); volume = std::max( 0.0, rsSBHissU->gain() - 0.1 * Deltatime );
rsSBHissU.gain( volume ); rsSBHissU->gain( volume );
if( volume < 0.05 ) { if( volume < 0.05 ) {
rsSBHissU.stop(); rsSBHissU->stop();
}
} }
} }
@@ -7471,97 +7483,105 @@ TTrain::update_sounds( double const Deltatime ) {
if( ( mvOccupied->BrakeHandle == TBrakeHandle::FV4a ) if( ( mvOccupied->BrakeHandle == TBrakeHandle::FV4a )
|| ( mvOccupied->BrakeHandle == TBrakeHandle::FVel6 ) ) { || ( mvOccupied->BrakeHandle == TBrakeHandle::FVel6 ) ) {
// upuszczanie z PG // upuszczanie z PG
if( rsHiss ) {
fPPress = interpolate( fPPress, static_cast<float>( mvOccupied->Handle->GetSound( s_fv4a_b ) ), 0.05f ); fPPress = interpolate( fPPress, static_cast<float>( mvOccupied->Handle->GetSound( s_fv4a_b ) ), 0.05f );
volume = ( volume = (
fPPress > 0 ? fPPress > 0 ?
rsHiss.m_amplitudefactor * fPPress * 0.25 : rsHiss->m_amplitudefactor * fPPress * 0.25 :
0 ); 0 );
if( volume * brakevolumescale > 0.05 ) { if( volume * brakevolumescale > 0.05 ) {
rsHiss rsHiss->gain( volume * brakevolumescale );
.gain( volume * brakevolumescale ) rsHiss->play( sound_flags::exclusive | sound_flags::looping );
.play( sound_flags::exclusive | sound_flags::looping );
} }
else { else {
rsHiss.stop(); rsHiss->stop();
}
} }
// napelnianie PG // napelnianie PG
if( rsHissU ) {
fNPress = interpolate( fNPress, static_cast<float>( mvOccupied->Handle->GetSound( s_fv4a_u ) ), 0.25f ); fNPress = interpolate( fNPress, static_cast<float>( mvOccupied->Handle->GetSound( s_fv4a_u ) ), 0.25f );
volume = ( volume = (
fNPress > 0 ? fNPress > 0 ?
rsHissU.m_amplitudefactor * fNPress : rsHissU->m_amplitudefactor * fNPress :
0 ); 0 );
if( volume * brakevolumescale > 0.05 ) { if( volume * brakevolumescale > 0.05 ) {
rsHissU rsHissU->gain( volume * brakevolumescale );
.gain( volume * brakevolumescale ) rsHissU->play( sound_flags::exclusive | sound_flags::looping );
.play( sound_flags::exclusive | sound_flags::looping );
} }
else { else {
rsHissU.stop(); rsHissU->stop();
}
} }
// upuszczanie przy naglym // upuszczanie przy naglym
volume = mvOccupied->Handle->GetSound( s_fv4a_e ) * rsHissE.m_amplitudefactor; if( rsHissE ) {
volume = mvOccupied->Handle->GetSound( s_fv4a_e ) * rsHissE->m_amplitudefactor;
if( volume * brakevolumescale > 0.05 ) { if( volume * brakevolumescale > 0.05 ) {
rsHissE rsHissE->gain( volume * brakevolumescale );
.gain( volume * brakevolumescale ) rsHissE->play( sound_flags::exclusive | sound_flags::looping );
.play( sound_flags::exclusive | sound_flags::looping );
} }
else { else {
rsHissE.stop(); rsHissE->stop();
}
} }
// upuszczanie sterujacego fala // upuszczanie sterujacego fala
volume = mvOccupied->Handle->GetSound( s_fv4a_x ) * rsHissX.m_amplitudefactor; if( rsHissX ) {
volume = mvOccupied->Handle->GetSound( s_fv4a_x ) * rsHissX->m_amplitudefactor;
if( volume * brakevolumescale > 0.05 ) { if( volume * brakevolumescale > 0.05 ) {
rsHissX rsHissX->gain( volume * brakevolumescale );
.gain( volume * brakevolumescale ) rsHissX->play( sound_flags::exclusive | sound_flags::looping );
.play( sound_flags::exclusive | sound_flags::looping );
} }
else { else {
rsHissX.stop(); rsHissX->stop();
}
} }
// upuszczanie z czasowego // upuszczanie z czasowego
volume = mvOccupied->Handle->GetSound( s_fv4a_t ) * rsHissT.m_amplitudefactor; if( rsHissT ) {
volume = mvOccupied->Handle->GetSound( s_fv4a_t ) * rsHissT->m_amplitudefactor;
if( volume * brakevolumescale > 0.05 ) { if( volume * brakevolumescale > 0.05 ) {
rsHissT rsHissT->gain( volume * brakevolumescale );
.gain( volume * brakevolumescale ) rsHissT->play( sound_flags::exclusive | sound_flags::looping );
.play( sound_flags::exclusive | sound_flags::looping );
} }
else { else {
rsHissT.stop(); rsHissT->stop();
}
} }
} else { } else {
// jesli nie FV4a // jesli nie FV4a
// upuszczanie z PG // upuszczanie z PG
if( rsHiss ) {
fPPress = ( 4.0f * fPPress + std::max( mvOccupied->dpLocalValve, mvOccupied->dpMainValve ) ) / ( 4.0f + 1.0f ); fPPress = ( 4.0f * fPPress + std::max( mvOccupied->dpLocalValve, mvOccupied->dpMainValve ) ) / ( 4.0f + 1.0f );
volume = ( volume = (
fPPress > 0.0f ? fPPress > 0.0f ?
2.0 * rsHiss.m_amplitudefactor * fPPress : 2.0 * rsHiss->m_amplitudefactor * fPPress :
0.0 ); 0.0 );
if( volume > 0.05 ) { if( volume > 0.05 ) {
rsHiss rsHiss->gain( volume );
.gain( volume ) rsHiss->play( sound_flags::exclusive | sound_flags::looping );
.play( sound_flags::exclusive | sound_flags::looping );
} }
else { else {
rsHiss.stop(); rsHiss->stop();
}
} }
// napelnianie PG // napelnianie PG
if( rsHissU ) {
fNPress = ( 4.0f * fNPress + Min0R( mvOccupied->dpLocalValve, mvOccupied->dpMainValve ) ) / ( 4.0f + 1.0f ); fNPress = ( 4.0f * fNPress + Min0R( mvOccupied->dpLocalValve, mvOccupied->dpMainValve ) ) / ( 4.0f + 1.0f );
volume = ( volume = (
fNPress < 0.0f ? fNPress < 0.0f ?
-1.0 * rsHissU.m_amplitudefactor * fNPress : -1.0 * rsHissU->m_amplitudefactor * fNPress :
0.0 ); 0.0 );
if( volume > 0.01 ) { if( volume > 0.01 ) {
rsHissU rsHissU->gain( volume );
.gain( volume ) rsHissU->play( sound_flags::exclusive | sound_flags::looping );
.play( sound_flags::exclusive | sound_flags::looping );
} }
else { else {
rsHissU.stop(); rsHissU->stop();
}
} }
} // koniec nie FV4a } // koniec nie FV4a
// brakes // brakes
if( rsBrake ) {
if( ( mvOccupied->UnitBrakeForce > 10.0 ) if( ( mvOccupied->UnitBrakeForce > 10.0 )
&& ( mvOccupied->Vel > 0.05 ) ) { && ( mvOccupied->Vel > 0.05 ) ) {
@@ -7573,49 +7593,54 @@ TTrain::update_sounds( double const Deltatime ) {
volume = ( volume = (
FreeFlyModeFlag ? FreeFlyModeFlag ?
0.0 : 0.0 :
rsBrake.m_amplitudeoffset rsBrake->m_amplitudeoffset
+ std::sqrt( brakeforceratio * interpolate( 0.4, 1.0, ( mvOccupied->Vel / ( 1 + mvOccupied->Vmax ) ) ) ) * rsBrake.m_amplitudefactor ); + std::sqrt( brakeforceratio * interpolate( 0.4, 1.0, ( mvOccupied->Vel / ( 1 + mvOccupied->Vmax ) ) ) ) * rsBrake->m_amplitudefactor );
rsBrake rsBrake->pitch( rsBrake->m_frequencyoffset + mvOccupied->Vel * rsBrake->m_frequencyfactor );
.pitch( rsBrake.m_frequencyoffset + mvOccupied->Vel * rsBrake.m_frequencyfactor ) rsBrake->gain( volume );
.gain( volume ) rsBrake->play( sound_flags::exclusive | sound_flags::looping );
.play( sound_flags::exclusive | sound_flags::looping );
} }
else { else {
rsBrake.stop(); rsBrake->stop();
}
} }
// ambient sound // ambient sound
// since it's typically ticking of the clock we can center it on tachometer or on middle of compartment bounding area // since it's typically ticking of the clock we can center it on tachometer or on middle of compartment bounding area
rsFadeSound.play( sound_flags::exclusive | sound_flags::looping ); if( rsFadeSound ) {
rsFadeSound->play( sound_flags::exclusive | sound_flags::looping );
}
if( mvControlled->TrainType == dt_181 ) { if( dsbSlipAlarm ) {
// alarm przy poslizgu dla 181/182 - BOMBARDIER // alarm przy poslizgu dla 181/182 - BOMBARDIER
if( ( mvControlled->SlippingWheels ) if( ( mvControlled->SlippingWheels )
&& ( DynamicObject->GetVelocity() > 1.0 ) ) { && ( DynamicObject->GetVelocity() > 1.0 ) ) {
dsbSlipAlarm.play( sound_flags::exclusive | sound_flags::looping ); dsbSlipAlarm->play( sound_flags::exclusive | sound_flags::looping );
} }
else { else {
dsbSlipAlarm.stop(); dsbSlipAlarm->stop();
} }
} }
// szum w czasie jazdy // szum w czasie jazdy
if( rsRunningNoise ) {
if( ( false == FreeFlyModeFlag ) if( ( false == FreeFlyModeFlag )
&& ( false == Global.CabWindowOpen ) && ( false == Global.CabWindowOpen )
&& ( DynamicObject->GetVelocity() > 0.5 ) ) { && ( DynamicObject->GetVelocity() > 0.5 ) ) {
update_sounds_runningnoise( rsRunningNoise ); update_sounds_runningnoise( *rsRunningNoise );
} }
else { else {
// don't play the optional ending sound if the listener switches views // don't play the optional ending sound if the listener switches views
rsRunningNoise.stop( true == FreeFlyModeFlag ); rsRunningNoise->stop( true == FreeFlyModeFlag );
}
} }
// hunting oscillation noise // hunting oscillation noise
if( rsHuntingNoise ) {
if( ( false == FreeFlyModeFlag ) if( ( false == FreeFlyModeFlag )
&& ( false == Global.CabWindowOpen ) && ( false == Global.CabWindowOpen )
&& ( DynamicObject->GetVelocity() > 0.5 ) && ( DynamicObject->GetVelocity() > 0.5 )
&& ( DynamicObject->IsHunting ) ) { && ( DynamicObject->IsHunting ) ) {
update_sounds_runningnoise( rsHuntingNoise ); update_sounds_runningnoise( *rsHuntingNoise );
// modify calculated sound volume by hunting amount // modify calculated sound volume by hunting amount
auto const huntingamount = auto const huntingamount =
interpolate( interpolate(
@@ -7624,63 +7649,68 @@ TTrain::update_sounds( double const Deltatime ) {
( mvOccupied->Vel - DynamicObject->HuntingShake.fadein_begin ) / ( DynamicObject->HuntingShake.fadein_end - DynamicObject->HuntingShake.fadein_begin ), ( mvOccupied->Vel - DynamicObject->HuntingShake.fadein_begin ) / ( DynamicObject->HuntingShake.fadein_end - DynamicObject->HuntingShake.fadein_begin ),
0.0, 1.0 ) ); 0.0, 1.0 ) );
rsHuntingNoise.gain( rsHuntingNoise.gain() * huntingamount ); rsHuntingNoise->gain( rsHuntingNoise->gain() * huntingamount );
} }
else { else {
// don't play the optional ending sound if the listener switches views // don't play the optional ending sound if the listener switches views
rsHuntingNoise.stop( true == FreeFlyModeFlag ); rsHuntingNoise->stop( true == FreeFlyModeFlag );
}
} }
// rain sound // rain sound
if( m_rainsound ) {
if( ( false == FreeFlyModeFlag ) if( ( false == FreeFlyModeFlag )
&& ( false == Global.CabWindowOpen ) && ( false == Global.CabWindowOpen )
&& ( Global.Weather == "rain:" ) ) { && ( Global.Weather == "rain:" ) ) {
if( m_rainsound.is_combined() ) { if( m_rainsound->is_combined() ) {
m_rainsound.pitch( Global.Overcast - 1.0 ); m_rainsound->pitch( Global.Overcast - 1.0 );
} }
m_rainsound m_rainsound->gain( m_rainsound->m_amplitudeoffset + m_rainsound->m_amplitudefactor * 1.f );
.gain( m_rainsound.m_amplitudeoffset + m_rainsound.m_amplitudefactor * 1.f ) m_rainsound->play( sound_flags::exclusive | sound_flags::looping );
.play( sound_flags::exclusive | sound_flags::looping );
} }
else { else {
m_rainsound.stop(); m_rainsound->stop();
}
} }
if( dsbHasler ) {
if( fTachoCount >= 3.f ) { if( fTachoCount >= 3.f ) {
auto const frequency{ ( auto const frequency{ (
true == dsbHasler.is_combined() ? true == dsbHasler->is_combined() ?
fTachoVelocity * 0.01 : fTachoVelocity * 0.01 :
dsbHasler.m_frequencyoffset + dsbHasler.m_frequencyfactor ) }; dsbHasler->m_frequencyoffset + dsbHasler->m_frequencyfactor ) };
dsbHasler dsbHasler->pitch( frequency );
.pitch( frequency ) dsbHasler->gain( dsbHasler->m_amplitudeoffset + dsbHasler->m_amplitudefactor );
.gain( dsbHasler.m_amplitudeoffset + dsbHasler.m_amplitudefactor ) dsbHasler->play( sound_flags::exclusive | sound_flags::looping );
.play( sound_flags::exclusive | sound_flags::looping );
} }
else if( fTachoCount < 1.f ) { else if( fTachoCount < 1.f ) {
dsbHasler.stop(); dsbHasler->stop();
}
} }
// power-reliant sounds // power-reliant sounds
if( mvOccupied->Power24vIsAvailable || mvOccupied->Power110vIsAvailable ) { if( mvOccupied->Power24vIsAvailable || mvOccupied->Power110vIsAvailable ) {
// McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa // McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa
// hunter-091012: rozdzielenie alarmow // hunter-091012: rozdzielenie alarmow
if( dsbBuzzer ) {
if( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm ) if( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm )
|| TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ) { || TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ) {
if( false == dsbBuzzer.is_playing() ) { if( false == dsbBuzzer->is_playing() ) {
dsbBuzzer dsbBuzzer->pitch( dsbBuzzer->m_frequencyoffset + dsbBuzzer->m_frequencyfactor );
.pitch( dsbBuzzer.m_frequencyoffset + dsbBuzzer.m_frequencyfactor ) dsbBuzzer->gain( dsbBuzzer->m_amplitudeoffset + dsbBuzzer->m_amplitudefactor );
.gain( dsbBuzzer.m_amplitudeoffset + dsbBuzzer.m_amplitudefactor ) dsbBuzzer->play( sound_flags::looping );
.play( sound_flags::looping );
Console::BitsSet( 1 << 14 ); // ustawienie bitu 16 na PoKeys Console::BitsSet( 1 << 14 ); // ustawienie bitu 16 na PoKeys
} }
} }
else { else {
if( true == dsbBuzzer.is_playing() ) { if( true == dsbBuzzer->is_playing() ) {
dsbBuzzer.stop(); dsbBuzzer->stop();
Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys
} }
} }
}
// distance meter alert // distance meter alert
if( m_distancecounterclear ) {
auto const *owner{ ( auto const *owner{ (
DynamicObject->ctOwner != nullptr ? DynamicObject->ctOwner != nullptr ?
DynamicObject->ctOwner : DynamicObject->ctOwner :
@@ -7689,19 +7719,23 @@ TTrain::update_sounds( double const Deltatime ) {
// play assigned sound if the train travelled its full length since meter activation // play assigned sound if the train travelled its full length since meter activation
// TBD: check all combinations of directions and active cab // TBD: check all combinations of directions and active cab
m_distancecounter = -1.f; // turn off the meter after its task is done m_distancecounter = -1.f; // turn off the meter after its task is done
m_distancecounterclear m_distancecounterclear->pitch( m_distancecounterclear->m_frequencyoffset + m_distancecounterclear->m_frequencyfactor );
.pitch( m_distancecounterclear.m_frequencyoffset + m_distancecounterclear.m_frequencyfactor ) m_distancecounterclear->gain( m_distancecounterclear->m_amplitudeoffset + m_distancecounterclear->m_amplitudefactor );
.gain( m_distancecounterclear.m_amplitudeoffset + m_distancecounterclear.m_amplitudefactor ) m_distancecounterclear->play( sound_flags::exclusive );
.play( sound_flags::exclusive ); }
} }
} }
else { else {
// stop power-reliant sounds if power is cut // stop power-reliant sounds if power is cut
if( true == dsbBuzzer.is_playing() ) { if( dsbBuzzer ) {
dsbBuzzer.stop(); if( true == dsbBuzzer->is_playing() ) {
dsbBuzzer->stop();
Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys
} }
m_distancecounterclear.stop(); }
if( m_distancecounterclear ) {
m_distancecounterclear->stop();
}
} }
update_sounds_radio(); update_sounds_radio();
@@ -7784,12 +7818,14 @@ void TTrain::update_sounds_radio() {
message.second->gain( volume ); message.second->gain( volume );
} }
// radiostop // radiostop
if( m_radiostop ) {
if( ( true == radioenabled ) if( ( true == radioenabled )
&& ( true == mvOccupied->RadioStopFlag ) ) { && ( true == mvOccupied->RadioStopFlag ) ) {
m_radiostop.play( sound_flags::exclusive | sound_flags::looping ); m_radiostop->play( sound_flags::exclusive | sound_flags::looping );
} }
else { else {
m_radiostop.stop(); m_radiostop->stop();
}
} }
} }
@@ -7832,10 +7868,43 @@ bool TTrain::CabChange(int iDirection)
// wczytywanie pliku z danymi multimedialnymi (dzwieki, kontrolki, kabiny) // wczytywanie pliku z danymi multimedialnymi (dzwieki, kontrolki, kabiny)
bool TTrain::LoadMMediaFile(std::string const &asFileName) bool TTrain::LoadMMediaFile(std::string const &asFileName)
{ {
// initialize sounds so potential entries from previous vehicle don't stick around
std::unordered_map<
std::string,
std::tuple<std::optional<sound_source> &, sound_placement, float, sound_type, int, double>>
internalsounds = {
{"ctrl:", {dsbNastawnikJazdy, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"ctrlscnd:", {dsbNastawnikBocz, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"reverserkey:", {dsbReverserKey, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"buzzer:", {dsbBuzzer, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"radiostop:", {m_radiostop, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"slipalarm:", {dsbSlipAlarm, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"distancecounter:", {m_distancecounterclear, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"tachoclock:", {dsbHasler, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"switch:", {dsbSwitch, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"pneumaticswitch:", {dsbPneumaticSwitch, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"airsound:", {rsHiss, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, sound_parameters::amplitude, 100.0}},
{"airsound2:", {rsHissU, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, sound_parameters::amplitude, 100.0}},
{"airsound3:", {rsHissE, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, sound_parameters::amplitude, 100.0}},
{"airsound4:", {rsHissX, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, sound_parameters::amplitude, 100.0}},
{"airsound5:", {rsHissT, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, sound_parameters::amplitude, 100.0}},
{"localbrakesound:", {rsSBHiss, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, sound_parameters::amplitude, 100.0}},
{"localbrakesound2:", {rsSBHissU, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, sound_parameters::amplitude, 100.0}},
{"brakesound:", {rsBrake, sound_placement::internal, -1, sound_type::single, sound_parameters::amplitude | sound_parameters::frequency, 100.0}},
{"fadesound:", {rsFadeSound, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"runningnoise:", {rsRunningNoise, sound_placement::internal, EU07_SOUND_GLOBALRANGE, sound_type::single, sound_parameters::amplitude | sound_parameters::frequency, mvOccupied->Vmax }},
{"huntingnoise:", {rsHuntingNoise, sound_placement::internal, EU07_SOUND_GLOBALRANGE, sound_type::single, sound_parameters::amplitude | sound_parameters::frequency, mvOccupied->Vmax }},
{"rainsound:", {m_rainsound, sound_placement::internal, -1, sound_type::single, 0, 100.0}},
};
for( auto &soundconfig : internalsounds ) {
std::get<std::optional<sound_source> &>( soundconfig.second ).reset();
}
// NOTE: since radiosound is an incomplete template not using std::optional it gets a special treatment
m_radiosound.owner( DynamicObject );
cParser parser( asFileName, cParser::buffer_FILE, DynamicObject->asBaseDir ); cParser parser( asFileName, cParser::buffer_FILE, DynamicObject->asBaseDir );
// NOTE: yaml-style comments are disabled until conflict in use of # is resolved // NOTE: yaml-style comments are disabled until conflict in use of # is resolved
// parser.addCommentStyle( "#", "\n" ); // parser.addCommentStyle( "#", "\n" );
std::string token; std::string token;
do do
{ {
@@ -7844,145 +7913,56 @@ bool TTrain::LoadMMediaFile(std::string const &asFileName)
parser >> token; parser >> token;
} while ((token != "") && (token != "internaldata:")); } while ((token != "") && (token != "internaldata:"));
if (token == "internaldata:") if (token == "internaldata:") {
{
do do {
{
token = ""; token = "";
parser.getTokens(); parser.getTokens();
parser >> token; parser >> token;
// SEKCJA DZWIEKOW
if (token == "ctrl:") { auto lookup { internalsounds.find( token ) };
// nastawnik: if( lookup == internalsounds.end() ) { continue; }
dsbNastawnikJazdy.deserialize( parser, sound_type::single );
dsbNastawnikJazdy.owner( DynamicObject ); auto const soundconfig { lookup->second };
sound_source sound {
std::get<sound_placement>( soundconfig ),
std::get<float>( soundconfig ) };
sound.deserialize(
parser,
std::get<sound_type>( soundconfig ),
std::get<int>( soundconfig ),
std::get<double>( soundconfig ) );
sound.owner( DynamicObject );
std::get<std::optional<sound_source> &>( soundconfig ) = sound;
} while( token != "" );
// assign default samples to sound emitters which weren't included in the config file
if( !m_rainsound ) {
sound_source rainsound;
rainsound.deserialize( "rainsound_default", sound_type::single );
rainsound.owner( DynamicObject );
m_rainsound = rainsound;
} }
else if (token == "ctrlscnd:") { if (!rsSBHiss) {
// hunter-081211: nastawnik bocznikowania
dsbNastawnikBocz.deserialize( parser, sound_type::single );
dsbNastawnikBocz.owner( DynamicObject );
}
else if (token == "reverserkey:") {
// hunter-131211: dzwiek kierunkowego
dsbReverserKey.deserialize( parser, sound_type::single );
dsbReverserKey.owner( DynamicObject );
}
else if (token == "buzzer:") {
// bzyczek shp:
dsbBuzzer.deserialize( parser, sound_type::single );
dsbBuzzer.owner( DynamicObject );
}
else if( token == "radiostop:" ) {
// radiostop
m_radiostop.deserialize( parser, sound_type::single );
m_radiostop.owner( DynamicObject );
}
else if (token == "slipalarm:") {
// Bombardier 011010: alarm przy poslizgu:
dsbSlipAlarm.deserialize( parser, sound_type::single );
dsbSlipAlarm.owner( DynamicObject );
}
else if (token == "distancecounter:") {
// distance meter 'good to go' sound
m_distancecounterclear.deserialize( parser, sound_type::single );
m_distancecounterclear.owner( DynamicObject );
}
else if (token == "tachoclock:") {
// cykanie rejestratora:
dsbHasler.deserialize( parser, sound_type::single );
dsbHasler.owner( DynamicObject );
}
else if (token == "switch:") {
// przelaczniki:
dsbSwitch.deserialize( parser, sound_type::single );
dsbSwitch.owner( DynamicObject );
}
else if (token == "pneumaticswitch:") {
// stycznik EP:
dsbPneumaticSwitch.deserialize( parser, sound_type::single );
dsbPneumaticSwitch.owner( DynamicObject );
}
else if (token == "airsound:") {
// syk:
rsHiss.deserialize( parser, sound_type::single, sound_parameters::amplitude );
rsHiss.owner( DynamicObject );
if( true == rsSBHiss.empty() ) {
// fallback for vehicles without defined local brake hiss sound // fallback for vehicles without defined local brake hiss sound
rsSBHiss = rsHiss; rsSBHiss = rsHiss;
} }
} if (!rsSBHissU) {
else if (token == "airsound2:") {
// syk:
rsHissU.deserialize( parser, sound_type::single, sound_parameters::amplitude );
rsHissU.owner( DynamicObject );
if( true == rsSBHissU.empty() ) {
// fallback for vehicles without defined local brake hiss sound // fallback for vehicles without defined local brake hiss sound
rsSBHissU = rsHissU; rsSBHissU = rsHissU;
} }
if (rsBrake) {
rsBrake->m_frequencyfactor /= (1 + mvOccupied->Vmax);
} }
else if (token == "airsound3:") { if (rsRunningNoise) {
// syk: rsRunningNoise->m_frequencyfactor /= (1 + mvOccupied->Vmax);
rsHissE.deserialize( parser, sound_type::single, sound_parameters::amplitude );
rsHissE.owner( DynamicObject );
} }
else if (token == "airsound4:") { if (rsHuntingNoise) {
// syk: rsHuntingNoise->m_frequencyfactor /= (1 + mvOccupied->Vmax);
rsHissX.deserialize( parser, sound_type::single, sound_parameters::amplitude );
rsHissX.owner( DynamicObject );
} }
else if (token == "airsound5:") {
// syk:
rsHissT.deserialize( parser, sound_type::single, sound_parameters::amplitude );
rsHissT.owner( DynamicObject );
}
else if (token == "localbrakesound:") {
// syk:
rsSBHiss.deserialize( parser, sound_type::single, sound_parameters::amplitude );
rsSBHiss.owner( DynamicObject );
}
else if( token == "localbrakesound2:" ) {
// syk:
rsSBHissU.deserialize( parser, sound_type::single, sound_parameters::amplitude );
rsSBHissU.owner( DynamicObject );
}
else if( token == "brakesound:" ) {
// the sound of vehicle body vibrations etc, when brakes are engaged
rsBrake.deserialize( parser, sound_type::single, sound_parameters::amplitude | sound_parameters::frequency );
rsBrake.owner( DynamicObject );
// NOTE: can't pre-calculate amplitude normalization based on max brake force, as this varies depending on vehicle speed
rsBrake.m_frequencyfactor /= ( 1 + mvOccupied->Vmax );
}
else if (token == "fadesound:") {
// ambient sound:
rsFadeSound.deserialize( parser, sound_type::single );
rsFadeSound.owner( DynamicObject );
}
else if( token == "runningnoise:" ) {
// szum podczas jazdy:
rsRunningNoise.deserialize( parser, sound_type::single, sound_parameters::amplitude | sound_parameters::frequency, mvOccupied->Vmax );
rsRunningNoise.owner( DynamicObject );
rsRunningNoise.m_frequencyfactor /= ( 1 + mvOccupied->Vmax );
}
else if( token == "huntingnoise:" ) {
// hunting oscillation sound:
rsHuntingNoise.deserialize( parser, sound_type::single, sound_parameters::amplitude | sound_parameters::frequency, mvOccupied->Vmax );
rsHuntingNoise.owner( DynamicObject );
rsHuntingNoise.m_frequencyfactor /= ( 1 + mvOccupied->Vmax );
}
else if( token == "rainsound:" ) {
// precipitation sound:
m_rainsound.deserialize( parser, sound_type::single );
m_rainsound.owner( DynamicObject );
} }
} while (token != "");
}
/*
else
{
return false;
} // nie znalazl sekcji internal
*/
return true; return true;
} }
@@ -7991,19 +7971,21 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
m_controlmapper.clear(); m_controlmapper.clear();
// clear python screens // clear python screens
m_screens.clear(); m_screens.clear();
// reset sound positions and owner // reset sound positions
auto const nullvector { glm::vec3() }; auto const nullvector { glm::vec3() };
std::vector<sound_source *> sounds = { std::vector<std::reference_wrapper<std::optional<sound_source>>> sounds = {
&dsbReverserKey, &dsbNastawnikJazdy, &dsbNastawnikBocz, dsbReverserKey, dsbNastawnikJazdy, dsbNastawnikBocz,
&dsbSwitch, &dsbPneumaticSwitch, dsbSwitch, dsbPneumaticSwitch,
&rsHiss, &rsHissU, &rsHissE, &rsHissX, &rsHissT, &rsSBHiss, &rsSBHissU, rsHiss, rsHissU, rsHissE, rsHissX, rsHissT, rsSBHiss, rsSBHissU,
&rsFadeSound, &rsRunningNoise, &rsHuntingNoise, rsFadeSound, rsRunningNoise, rsHuntingNoise,
&dsbHasler, &dsbBuzzer, &dsbSlipAlarm, &m_distancecounterclear, &m_radiosound, &m_radiostop dsbHasler, dsbBuzzer, dsbSlipAlarm, m_distancecounterclear, m_rainsound, m_radiostop
}; };
for( auto sound : sounds ) { for( auto &sound : sounds ) {
sound->offset( nullvector ); if( sound.get() ) {
sound->owner( DynamicObject ); sound.get()->offset( nullvector );
} }
}
m_radiosound.offset( nullvector );
// reset view angles // reset view angles
pMechViewAngle = { 0.0, 0.0 }; pMechViewAngle = { 0.0, 0.0 };
@@ -8011,7 +7993,7 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
bool parse = false; bool parse = false;
int cabindex = 0; int cabindex = 0;
DynamicObject->mdKabina = NULL; // likwidacja wskaźnika na dotychczasową kabinę DynamicObject->mdKabina = nullptr; // likwidacja wskaźnika na dotychczasową kabinę
switch (NewCabNo) switch (NewCabNo)
{ // ustalenie numeru kabiny do wczytania { // ustalenie numeru kabiny do wczytania
case -1: case -1:
@@ -8038,59 +8020,8 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
token = ""; token = "";
parser.getTokens(); parser.getTokens();
parser >> token; parser >> token;
/*
if( token == "locations:" ) {
do {
token = "";
parser.getTokens(); parser >> token;
if( token == "radio:" ) {
// point in 3d space, in format [ x, y, z ]
glm::vec3 radiolocation;
parser.getTokens( 3, false, "\n\r\t ,;[]" );
parser
>> radiolocation.x
>> radiolocation.y
>> radiolocation.z;
radiolocation *= glm::vec3( NewCabNo, 1, NewCabNo );
m_radiosound.offset( radiolocation );
}
else if( token == "alerter:" ) {
// point in 3d space, in format [ x, y, z ]
glm::vec3 alerterlocation;
parser.getTokens( 3, false, "\n\r\t ,;[]" );
parser
>> alerterlocation.x
>> alerterlocation.y
>> alerterlocation.z;
alerterlocation *= glm::vec3( NewCabNo, 1, NewCabNo );
dsbBuzzer.offset( alerterlocation );
}
} while( ( token != "" )
&& ( token != "endlocations" ) );
} // locations:
*/
} while ((token != "") && (token != cabstr)); } while ((token != "") && (token != cabstr));
/*
if ((cabindex != 1) && (token != cabstr))
{
// jeśli nie znaleziony wpis kabiny, próba szukania kabiny 1
cabstr = "cab1definition:";
// crude way to start parsing from beginning
parser = std::make_shared<cParser>(asFileName, cParser::buffer_FILE);
// NOTE: yaml-style comments are disabled until conflict in use of # is resolved
// parser.addCommentStyle( "#", "\n" );
do
{
token = "";
parser.getTokens();
parser >> token;
} while ((token != "") && (token != cabstr));
}
*/
if (token == cabstr) if (token == cabstr)
{ {
// jeśli znaleziony wpis kabiny // jeśli znaleziony wpis kabiny
@@ -8288,63 +8219,53 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
if (DynamicObject->mdKabina) if (DynamicObject->mdKabina)
{ {
*/ */
// assign default samples to sound emitters which weren't included in the config file
if( m_rainsound.empty() ) {
m_rainsound.deserialize( "rainsound_default", sound_type::single );
m_rainsound.owner( DynamicObject );
}
// configure placement of sound emitters which aren't bound with any device model, and weren't placed manually // configure placement of sound emitters which aren't bound with any device model, and weren't placed manually
// try first to bind sounds to location of possible devices auto const caboffset { glm::dvec3 { ( Cabine[ cabindex ].CabPos1 + Cabine[ cabindex ].CabPos2 ) * 0.5 } +glm::dvec3 { 0, 1, 0 } };
if( dsbReverserKey.offset() == nullvector ) { // NOTE: since radiosound is an incomplete template not using std::optional it gets a special treatment
dsbReverserKey.offset( ggDirKey.model_offset() );
}
if( dsbNastawnikJazdy.offset() == nullvector ) {
dsbNastawnikJazdy.offset( ggJointCtrl.model_offset() );
}
if( dsbNastawnikJazdy.offset() == nullvector ) {
dsbNastawnikJazdy.offset( ggMainCtrl.model_offset() );
}
if( dsbNastawnikBocz.offset() == nullvector ) {
dsbNastawnikBocz.offset( ggScndCtrl.model_offset() );
}
if( dsbBuzzer.offset() == nullvector ) {
dsbBuzzer.offset( btLampkaCzuwaka.model_offset() );
}
// HACK: alerter is likely to be located somewhere near computer displays
if( m_distancecounterclear.offset() == nullvector ) {
m_distancecounterclear.offset( btLampkaCzuwaka.model_offset() );
}
// radio has two potential items which can provide the position
if( m_radiosound.offset() == nullvector ) { if( m_radiosound.offset() == nullvector ) {
m_radiosound.offset( btLampkaRadio.model_offset() ); m_radiosound.offset( btLampkaRadio.model_offset() );
} }
if( m_radiostop.offset() == nullvector ) { if( m_radiosound.offset() == nullvector ) {
m_radiostop.offset( m_radiosound.offset() ); m_radiosound.offset( caboffset );
} }
auto const localbrakeoffset { ggLocalBrake.model_offset() }; std::vector<std::pair<std::reference_wrapper<std::optional<sound_source>>, glm::vec3>>
std::vector<sound_source *> localbrakesounds = { soundlocations = {
&rsSBHiss, &rsSBHissU {dsbReverserKey, ggDirKey.model_offset()},
{dsbNastawnikJazdy, ggJointCtrl.model_offset()},
{dsbNastawnikJazdy, ggMainCtrl.model_offset()}, // NOTE: fallback for vehicles without universal controller
{dsbNastawnikBocz, ggScndCtrl.model_offset()},
{dsbSwitch, caboffset},
{dsbPneumaticSwitch, caboffset},
{rsHiss, ggBrakeCtrl.model_offset()},
{rsHissU, ggBrakeCtrl.model_offset()},
{rsHissE, ggBrakeCtrl.model_offset()},
{rsHissX, ggBrakeCtrl.model_offset()},
{rsHissT, ggBrakeCtrl.model_offset()},
{rsSBHiss, ggLocalBrake.model_offset()},
{rsSBHiss, ggBrakeCtrl.model_offset()}, // NOTE: fallback if the local brake model can't be located
{rsSBHissU, ggLocalBrake.model_offset()},
{rsSBHissU, ggBrakeCtrl.model_offset()}, // NOTE: fallback if the local brake model can't be located
{rsFadeSound, caboffset},
{rsRunningNoise, caboffset},
{rsHuntingNoise, caboffset},
{dsbHasler, caboffset},
{dsbBuzzer, btLampkaCzuwaka.model_offset()},
{dsbSlipAlarm, caboffset},
{m_distancecounterclear, btLampkaCzuwaka.model_offset()},
{m_rainsound, caboffset},
{m_radiostop, m_radiosound.offset()},
}; };
for( auto sound : localbrakesounds ) { for( auto & sound : soundlocations ) {
if( sound->offset() == nullvector ) { if( ( sound.first.get() )
sound->offset( localbrakeoffset ); && ( sound.first.get()->offset() == nullvector ) ) {
sound.first.get()->offset( sound.second );
} }
} }
// NOTE: if the local brake model can't be located the emitter will also be assigned location of main brake // second pass, in case some items received no positioning due to missing submodels etc
auto const brakeoffset { ggBrakeCtrl.model_offset() }; for( auto & sound : soundlocations ) {
std::vector<sound_source *> brakesounds = { if( ( sound.first.get() )
&rsHiss, &rsHissU, &rsHissE, &rsHissX, &rsHissT, &rsSBHiss, &rsSBHissU, && ( sound.first.get()->offset() == nullvector ) ) {
}; sound.first.get()->offset( caboffset );
for( auto sound : brakesounds ) {
if( sound->offset() == nullvector ) {
sound->offset( brakeoffset );
}
}
// for whatever is left fallback on generic location, centre of the cab
auto const caboffset { glm::dvec3 { ( Cabine[ cabindex ].CabPos1 + Cabine[ cabindex ].CabPos2 ) * 0.5 } + glm::dvec3 { 0, 1, 0 } };
for( auto sound : sounds ) {
if( sound->offset() == nullvector ) {
sound->offset( caboffset );
} }
} }
@@ -8521,9 +8442,13 @@ TTrain::MoveToVehicle(TDynamicObject *target) {
DynamicSet(target); DynamicSet(target);
} }
{
auto const filename { Occupied()->TypeName + ".mmd" };
LoadMMediaFile( filename );
InitializeCab( InitializeCab(
Occupied()->CabActive, Occupied()->CabActive,
Occupied()->TypeName + ".mmd" ); filename );
}
Dynamic()->ABuSetModelShake( {} ); // zerowanie przesunięcia przed powrotem? Dynamic()->ABuSetModelShake( {} ); // zerowanie przesunięcia przed powrotem?
@@ -9544,8 +9469,9 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
gauge.Load(Parser, DynamicObject); gauge.Load(Parser, DynamicObject);
gauge.AssignFloat(&fTachoVelocityJump); gauge.AssignFloat(&fTachoVelocityJump);
// bind tachometer sound location to the meter // bind tachometer sound location to the meter
if( dsbHasler.offset() == glm::vec3() ) { if( dsbHasler
dsbHasler.offset( gauge.model_offset() ); && dsbHasler->offset() == glm::vec3() ) {
dsbHasler->offset( gauge.model_offset() );
} }
} }
else if (Label == "tachometern:") else if (Label == "tachometern:")
@@ -9555,8 +9481,9 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
gauge.Load(Parser, DynamicObject); gauge.Load(Parser, DynamicObject);
gauge.AssignFloat(&fTachoVelocity); gauge.AssignFloat(&fTachoVelocity);
// bind tachometer sound location to the meter // bind tachometer sound location to the meter
if( dsbHasler.offset() == glm::vec3() ) { if( dsbHasler
dsbHasler.offset( gauge.model_offset() ); && dsbHasler->offset() == glm::vec3() ) {
dsbHasler->offset( gauge.model_offset() );
} }
} }
else if (Label == "tachometerd:") else if (Label == "tachometerd:")
@@ -9566,8 +9493,9 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
gauge.Load(Parser, DynamicObject); gauge.Load(Parser, DynamicObject);
gauge.AssignFloat(&fTachoVelocity); gauge.AssignFloat(&fTachoVelocity);
// bind tachometer sound location to the meter // bind tachometer sound location to the meter
if( dsbHasler.offset() == glm::vec3() ) { if( dsbHasler
dsbHasler.offset( gauge.model_offset() ); && dsbHasler->offset() == glm::vec3() ) {
dsbHasler->offset( gauge.model_offset() );
} }
} }
else if ((Label == "hvcurrent1:") || (Label == "hvcurrent1b:")) else if ((Label == "hvcurrent1:") || (Label == "hvcurrent1b:"))

52
Train.h
View File

@@ -728,35 +728,33 @@ public: // reszta może by?publiczna
TButton btHaslerBrakes; // ciśnienie w cylindrach TButton btHaslerBrakes; // ciśnienie w cylindrach
TButton btHaslerCurrent; // prąd na silnikach TButton btHaslerCurrent; // prąd na silnikach
sound_source dsbReverserKey { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // hunter-121211 std::optional<sound_source>
sound_source dsbNastawnikJazdy { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; dsbNastawnikJazdy,
sound_source dsbNastawnikBocz { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // hunter-081211 dsbNastawnikBocz,
sound_source dsbSwitch { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; dsbReverserKey,
sound_source dsbPneumaticSwitch { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; dsbBuzzer,
m_radiostop,
sound_source rsHiss { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // upuszczanie dsbSlipAlarm,
sound_source rsHissU { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // napelnianie m_distancecounterclear,
sound_source rsHissE { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // nagle dsbHasler,
sound_source rsHissX { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // fala dsbSwitch,
sound_source rsHissT { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // czasowy dsbPneumaticSwitch,
sound_source rsSBHiss { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // local rsHiss,
sound_source rsSBHissU { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // local, engage brakes rsHissU,
float m_lastlocalbrakepressure { -1.f }; // helper, cached level of pressure in local brake cylinder rsHissE,
float m_localbrakepressurechange { 0.f }; // recent change of pressure in local brake cylinder rsHissX,
sound_source rsBrake { sound_placement::internal, -1 }; rsHissT,
rsSBHiss,
sound_source rsFadeSound { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; rsSBHissU,
sound_source rsRunningNoise{ sound_placement::internal, EU07_SOUND_GLOBALRANGE }; rsBrake,
sound_source rsHuntingNoise{ sound_placement::internal, EU07_SOUND_GLOBALRANGE }; rsFadeSound,
sound_source m_rainsound { sound_placement::internal, -1 }; rsRunningNoise,
rsHuntingNoise,
sound_source dsbHasler { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; m_rainsound;
sound_source dsbBuzzer { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
sound_source dsbSlipAlarm { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // Bombardier 011010: alarm przy poslizgu dla 181/182
sound_source m_radiosound { sound_placement::internal, 2 * EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // cached template for radio messages sound_source m_radiosound { sound_placement::internal, 2 * EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // cached template for radio messages
std::vector<std::pair<int, std::shared_ptr<sound_source>>> m_radiomessages; // list of currently played radio messages std::vector<std::pair<int, std::shared_ptr<sound_source>>> m_radiomessages; // list of currently played radio messages
sound_source m_radiostop { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; float m_lastlocalbrakepressure { -1.f }; // helper, cached level of pressure in local brake cylinder
sound_source m_distancecounterclear { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // distance meter 'good to go' alert float m_localbrakepressurechange { 0.f }; // recent change of pressure in local brake cylinder
/* /*
int iCabLightFlag; // McZapkie:120503: oswietlenie kabiny (0: wyl, 1: przyciemnione, 2: pelne) int iCabLightFlag; // McZapkie:120503: oswietlenie kabiny (0: wyl, 1: przyciemnione, 2: pelne)
bool bCabLight; // hunter-091012: czy swiatlo jest zapalone? bool bCabLight; // hunter-091012: czy swiatlo jest zapalone?

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#define VERSION_MAJOR 21 #define VERSION_MAJOR 21
#define VERSION_MINOR 426 #define VERSION_MINOR 508
#define VERSION_REVISION 0 #define VERSION_REVISION 0