mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 15:09:19 +02:00
audio source reinitialization fix, sound volume level tweaks
This commit is contained in:
52
Driver.cpp
52
Driver.cpp
@@ -2987,7 +2987,8 @@ void TController::Doors(bool what)
|
|||||||
if (mvOccupied->DoorOpenCtrl == 1)
|
if (mvOccupied->DoorOpenCtrl == 1)
|
||||||
{ // jeśli drzwi sterowane z kabiny
|
{ // jeśli drzwi sterowane z kabiny
|
||||||
if( AIControllFlag ) {
|
if( AIControllFlag ) {
|
||||||
if( mvOccupied->DoorLeftOpened || mvOccupied->DoorRightOpened ) { // AI zamyka drzwi przed odjazdem
|
if( mvOccupied->DoorLeftOpened || mvOccupied->DoorRightOpened ) {
|
||||||
|
// AI zamyka drzwi przed odjazdem
|
||||||
if( ( true == mvOccupied->DoorClosureWarning )
|
if( ( true == mvOccupied->DoorClosureWarning )
|
||||||
&& ( false == mvOccupied->DepartureSignal )
|
&& ( false == mvOccupied->DepartureSignal )
|
||||||
&& ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) {
|
&& ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) {
|
||||||
@@ -3092,8 +3093,8 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
|
|||||||
asNextStop = TrainParams->NextStop();
|
asNextStop = TrainParams->NextStop();
|
||||||
iDrivigFlags |= movePrimary; // skoro dostał rozkład, to jest teraz głównym
|
iDrivigFlags |= movePrimary; // skoro dostał rozkład, to jest teraz głównym
|
||||||
NewCommand = Global::asCurrentSceneryPath + NewCommand + ".wav"; // na razie jeden
|
NewCommand = Global::asCurrentSceneryPath + NewCommand + ".wav"; // na razie jeden
|
||||||
if (FileExists(NewCommand))
|
if (FileExists(NewCommand)) {
|
||||||
{ // wczytanie dźwięku odjazdu podawanego bezpośrenido
|
// wczytanie dźwięku odjazdu podawanego bezpośrenido
|
||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||||
tsGuardSignal =
|
tsGuardSignal =
|
||||||
new TTextSound(
|
new TTextSound(
|
||||||
@@ -3101,19 +3102,15 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
|
|||||||
pVehicle->GetPosition().x, pVehicle->GetPosition().y, pVehicle->GetPosition().z,
|
pVehicle->GetPosition().x, pVehicle->GetPosition().y, pVehicle->GetPosition().z,
|
||||||
false);
|
false);
|
||||||
#else
|
#else
|
||||||
tsGuardSignal = new sound_source( sound_placement::external );
|
tsGuardSignal = new sound_source( sound_placement::external, 75.f );
|
||||||
tsGuardSignal->deserialize( NewCommand, sound_type::single );
|
tsGuardSignal->deserialize( NewCommand, sound_type::single );
|
||||||
tsGuardSignal->owner( pVehicle );
|
|
||||||
// place virtual conductor some distance away
|
|
||||||
tsGuardSignal->offset( { pVehicle->MoverParameters->Dim.W * -0.75f, 1.7f, fLength * -0.25f } );
|
|
||||||
#endif
|
#endif
|
||||||
iGuardRadio = 0; // nie przez radio
|
iGuardRadio = 0; // nie przez radio
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
NewCommand = NewCommand.insert(NewCommand.find_last_of("."),"radio"); // wstawienie przed kropkč
|
NewCommand = NewCommand.insert(NewCommand.find_last_of("."),"radio"); // wstawienie przed kropkč
|
||||||
if (FileExists(NewCommand))
|
if (FileExists(NewCommand)) {
|
||||||
{ // wczytanie dźwięku odjazdu w wersji radiowej (słychać tylko w kabinie)
|
// wczytanie dźwięku odjazdu w wersji radiowej (słychać tylko w kabinie)
|
||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||||
tsGuardSignal =
|
tsGuardSignal =
|
||||||
new TTextSound(
|
new TTextSound(
|
||||||
@@ -3121,12 +3118,8 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
|
|||||||
pVehicle->GetPosition().x, pVehicle->GetPosition().y, pVehicle->GetPosition().z,
|
pVehicle->GetPosition().x, pVehicle->GetPosition().y, pVehicle->GetPosition().z,
|
||||||
false);
|
false);
|
||||||
#else
|
#else
|
||||||
tsGuardSignal = new sound_source( sound_placement::external );
|
tsGuardSignal = new sound_source( sound_placement::internal, 2 * EU07_SOUND_CABCONTROLSCUTOFFRANGE );
|
||||||
tsGuardSignal->deserialize( NewCommand, sound_type::single );
|
tsGuardSignal->deserialize( NewCommand, sound_type::single );
|
||||||
tsGuardSignal->owner( pVehicle );
|
|
||||||
// command will be transmitted by radio
|
|
||||||
// TODO: put the exact location in the proper cab
|
|
||||||
tsGuardSignal->offset( { 0.f, 1.f, pVehicle->MoverParameters->Dim.L * 0.75f } );
|
|
||||||
#endif
|
#endif
|
||||||
iGuardRadio = iRadioChannel;
|
iGuardRadio = iRadioChannel;
|
||||||
}
|
}
|
||||||
@@ -4487,20 +4480,21 @@ TController::UpdateSituation(double dt) {
|
|||||||
}
|
}
|
||||||
if (VelDesired > 0.0)
|
if (VelDesired > 0.0)
|
||||||
if( ( ( iDrivigFlags & moveStopHere ) == 0 )
|
if( ( ( iDrivigFlags & moveStopHere ) == 0 )
|
||||||
|| ( ( SemNextIndex != -1 )
|
|| ( ( SemNextIndex != -1 )
|
||||||
&& ( SemNextIndex < sSpeedTable.size() ) // BUG: index can point at non-existing slot. investigate reason(s)
|
&& ( SemNextIndex < sSpeedTable.size() ) // BUG: index can point at non-existing slot. investigate reason(s)
|
||||||
&& ( sSpeedTable[SemNextIndex].fVelNext != 0.0 ) ) ) {
|
&& ( sSpeedTable[SemNextIndex].fVelNext != 0.0 ) ) ) {
|
||||||
// jeśli można jechać, to odpalić dźwięk kierownika oraz zamknąć drzwi w
|
// jeśli można jechać, to odpalić dźwięk kierownika oraz zamknąć drzwi w
|
||||||
// składzie, jeśli nie mamy czekać na sygnał też trzeba odpalić
|
// składzie, jeśli nie mamy czekać na sygnał też trzeba odpalić
|
||||||
if (iDrivigFlags & moveGuardSignal)
|
if (iDrivigFlags & moveGuardSignal)
|
||||||
{ // komunikat od kierownika tu, bo musi być wolna droga i odczekany czas stania
|
{ // komunikat od kierownika tu, bo musi być wolna droga i odczekany czas stania
|
||||||
iDrivigFlags &= ~moveGuardSignal; // tylko raz nadać
|
iDrivigFlags &= ~moveGuardSignal; // tylko raz nadać
|
||||||
|
/*
|
||||||
if( ( iDrivigFlags & moveDoorOpened )
|
if( ( iDrivigFlags & moveDoorOpened )
|
||||||
&& ( false == mvOccupied->DoorOpenCtrl ) ) {
|
&& ( false == mvOccupied->DoorOpenCtrl ) ) {
|
||||||
// jeśli drzwi otwarte, niesterowane przez maszynistę
|
// jeśli drzwi otwarte, niesterowane przez maszynistę
|
||||||
Doors( false ); // a EZT zamknie dopiero po odegraniu komunikatu kierownika
|
Doors( false ); // a EZT zamknie dopiero po odegraniu komunikatu kierownika
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if( tsGuardSignal != nullptr ) {
|
if( tsGuardSignal != nullptr ) {
|
||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||||
tsGuardSignal->Stop();
|
tsGuardSignal->Stop();
|
||||||
@@ -4513,11 +4507,14 @@ TController::UpdateSituation(double dt) {
|
|||||||
// pobliżu, a drugi radiowy, słyszalny w innych lokomotywach
|
// pobliżu, a drugi radiowy, słyszalny w innych lokomotywach
|
||||||
// na razie zakładam, że to nie jest dźwięk radiowy, bo trzeba by zrobić
|
// na razie zakładam, że to nie jest dźwięk radiowy, bo trzeba by zrobić
|
||||||
// obsługę kanałów radiowych itd.
|
// obsługę kanałów radiowych itd.
|
||||||
if( !iGuardRadio ) {
|
if( iGuardRadio == 0 ) {
|
||||||
// jeśli nie przez radio
|
// jeśli nie przez radio
|
||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||||
tsGuardSignal->Play( 1.0, 0, !FreeFlyModeFlag, pVehicle->GetPosition() ); // dla true jest głośniej
|
tsGuardSignal->Play( 1.0, 0, !FreeFlyModeFlag, pVehicle->GetPosition() ); // dla true jest głośniej
|
||||||
#else
|
#else
|
||||||
|
tsGuardSignal->owner( pVehicle );
|
||||||
|
// place virtual conductor some distance away
|
||||||
|
tsGuardSignal->offset( { pVehicle->MoverParameters->Dim.W * -0.75f, 1.7f, std::min( -20.0, -0.2 * fLength ) } );
|
||||||
tsGuardSignal->play( sound_flags::exclusive );
|
tsGuardSignal->play( sound_flags::exclusive );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -4526,15 +4523,18 @@ TController::UpdateSituation(double dt) {
|
|||||||
// if (!FreeFlyModeFlag) //obserwator musi być w środku pojazdu
|
// if (!FreeFlyModeFlag) //obserwator musi być w środku pojazdu
|
||||||
// (albo może mieć radio przenośne) - kierownik mógłby powtarzać
|
// (albo może mieć radio przenośne) - kierownik mógłby powtarzać
|
||||||
// przy braku reakcji
|
// przy braku reakcji
|
||||||
|
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||||
if( SquareMagnitude( pVehicle->GetPosition() - Global::pCameraPosition ) < 2000 * 2000 ) {
|
if( SquareMagnitude( pVehicle->GetPosition() - Global::pCameraPosition ) < 2000 * 2000 ) {
|
||||||
// w odległości mniejszej niż 2km
|
// w odległości mniejszej niż 2km
|
||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
|
||||||
tsGuardSignal->Play( 1.0, 0, true, pVehicle->GetPosition() ); // dźwięk niby przez radio
|
tsGuardSignal->Play( 1.0, 0, true, pVehicle->GetPosition() ); // dźwięk niby przez radio
|
||||||
#else
|
|
||||||
// TODO: proper system for sending/receiving radio messages
|
|
||||||
tsGuardSignal->play( sound_flags::exclusive );
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
// TODO: proper system for sending/receiving radio messages
|
||||||
|
// place the sound in appropriate cab of the manned vehicle
|
||||||
|
tsGuardSignal->owner( pVehicle );
|
||||||
|
tsGuardSignal->offset( { 0.f, 2.f, pVehicle->MoverParameters->Dim.L * 0.4f * ( pVehicle->MoverParameters->ActiveCab < 0 ? -1 : 1 ) } );
|
||||||
|
tsGuardSignal->play( sound_flags::exclusive );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
DynObj.cpp
12
DynObj.cpp
@@ -3605,6 +3605,8 @@ void TDynamicObject::RenderSounds() {
|
|||||||
double volume { 1.0 };
|
double volume { 1.0 };
|
||||||
double const dt { Timer::GetDeltaRenderTime() };
|
double const dt { Timer::GetDeltaRenderTime() };
|
||||||
|
|
||||||
|
if( dt == 0.0 ) { return; }
|
||||||
|
|
||||||
// engine sounds
|
// engine sounds
|
||||||
if( MoverParameters->Power > 0 ) {
|
if( MoverParameters->Power > 0 ) {
|
||||||
|
|
||||||
@@ -3889,7 +3891,7 @@ void TDynamicObject::RenderSounds() {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
eng_turbo = std::max( goalpitch, eng_turbo - changerate * 0.5 );
|
eng_turbo = std::max( goalpitch, eng_turbo - changerate * 0.5 );
|
||||||
volume = std::max( 0.0, sTurbo.gain() - 10.0 * dt );
|
volume = std::max( 0.0, sTurbo.gain() - 2.0 * dt );
|
||||||
if( volume > 0.05 ) {
|
if( volume > 0.05 ) {
|
||||||
sTurbo
|
sTurbo
|
||||||
.pitch( 0.4 + eng_turbo * 0.4 )
|
.pitch( 0.4 + eng_turbo * 0.4 )
|
||||||
@@ -3943,7 +3945,7 @@ void TDynamicObject::RenderSounds() {
|
|||||||
|
|
||||||
// brake system and braking sounds:
|
// brake system and braking sounds:
|
||||||
if( m_lastbrakepressure != -1.f ) {
|
if( m_lastbrakepressure != -1.f ) {
|
||||||
// calculate rate of pressure change in brake cylinder, once it's been initialized
|
// calculate rate of pressure drop in brake cylinder, once it's been initialized
|
||||||
auto const brakepressuredifference { m_lastbrakepressure - MoverParameters->BrakePress };
|
auto const brakepressuredifference { m_lastbrakepressure - MoverParameters->BrakePress };
|
||||||
m_brakepressurechange = interpolate<float>( m_brakepressurechange, 10 * ( brakepressuredifference / dt ), 0.1f );
|
m_brakepressurechange = interpolate<float>( m_brakepressurechange, 10 * ( brakepressuredifference / dt ), 0.1f );
|
||||||
}
|
}
|
||||||
@@ -3951,7 +3953,7 @@ void TDynamicObject::RenderSounds() {
|
|||||||
if( m_brakepressurechange > 0.05f ) {
|
if( m_brakepressurechange > 0.05f ) {
|
||||||
// NOTE: can't use the leak rate directly due to irregular results produced by some brake type implementations
|
// NOTE: can't use the leak rate directly due to irregular results produced by some brake type implementations
|
||||||
rsUnbrake
|
rsUnbrake
|
||||||
.gain( static_cast<float>( std::max( MoverParameters->BrakePress, 0.0 ) / MoverParameters->MaxBrakePress[ 3 ] ) )
|
.gain( static_cast<float>( 1.25 * std::max( MoverParameters->BrakePress, 0.0 ) / MoverParameters->MaxBrakePress[ 3 ] ) )
|
||||||
.play( sound_flags::exclusive | sound_flags::looping );
|
.play( sound_flags::exclusive | sound_flags::looping );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -4164,13 +4166,13 @@ void TDynamicObject::RenderSounds() {
|
|||||||
}
|
}
|
||||||
// scale volume by track quality
|
// scale volume by track quality
|
||||||
volume *= ( 20.0 + MyTrack->iDamageFlag ) / 21;
|
volume *= ( 20.0 + MyTrack->iDamageFlag ) / 21;
|
||||||
// scale volume with curve radius and vehicle speed
|
// scale volume with vehicle speed
|
||||||
// TBD, TODO: disable the scaling for sounds combined from speed-based samples?
|
// TBD, TODO: disable the scaling for sounds combined from speed-based samples?
|
||||||
volume *=
|
volume *=
|
||||||
interpolate(
|
interpolate(
|
||||||
0.0, 1.0,
|
0.0, 1.0,
|
||||||
clamp(
|
clamp(
|
||||||
MoverParameters->Vel / 80.0,
|
MoverParameters->Vel / 60.0,
|
||||||
0.0, 1.0 ) );
|
0.0, 1.0 ) );
|
||||||
rsRunningNoise
|
rsRunningNoise
|
||||||
.pitch( clamp( frequency, 0.5, 1.15 ) ) // arbitrary limits to prevent the pitch going out of whack
|
.pitch( clamp( frequency, 0.5, 1.15 ) ) // arbitrary limits to prevent the pitch going out of whack
|
||||||
|
|||||||
214
Train.cpp
214
Train.cpp
@@ -5130,120 +5130,128 @@ bool TTrain::Update( double const Deltatime )
|
|||||||
|
|
||||||
void
|
void
|
||||||
TTrain::update_sounds( double const Deltatime ) {
|
TTrain::update_sounds( double const Deltatime ) {
|
||||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
|
||||||
double vol = 0;
|
if( Deltatime == 0.0 ) { return; }
|
||||||
// int freq=1;
|
|
||||||
double dfreq;
|
double volume { 0.0 };
|
||||||
|
double const brakevolumescale { 0.5 };
|
||||||
|
|
||||||
// McZapkie-280302 - syczenie
|
// McZapkie-280302 - syczenie
|
||||||
if( ( mvOccupied->BrakeHandle == FV4a ) || ( mvOccupied->BrakeHandle == FVel6 ) ) {
|
// TODO: softer volume reduction than plain abrupt stop, perhaps as reusable wrapper?
|
||||||
if( rsHiss.AM != 0 ) // upuszczanie z PG
|
if( ( mvOccupied->BrakeHandle == FV4a )
|
||||||
{
|
|| ( mvOccupied->BrakeHandle == FVel6 ) ) {
|
||||||
fPPress = ( 1 * fPPress + mvOccupied->Handle->GetSound( s_fv4a_b ) ) / ( 2 );
|
// upuszczanie z PG
|
||||||
if( fPPress > 0 ) {
|
fPPress = interpolate<float>( fPPress, mvOccupied->Handle->GetSound( s_fv4a_b ), 0.05 );
|
||||||
vol = 2.0 * rsHiss.AM * fPPress;
|
volume = (
|
||||||
}
|
fPPress > 0 ?
|
||||||
if( vol > 0.001 ) {
|
rsHiss.m_amplitudefactor * fPPress * 0.25 :
|
||||||
rsHiss.Play( vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition() );
|
0 );
|
||||||
}
|
if( volume * brakevolumescale > 0.05 ) {
|
||||||
else {
|
rsHiss
|
||||||
rsHiss.Stop();
|
.gain( volume * brakevolumescale )
|
||||||
}
|
.play( sound_flags::exclusive | sound_flags::looping );
|
||||||
}
|
}
|
||||||
if( rsHissU.AM != 0 ) // upuszczanie z PG
|
else {
|
||||||
{
|
rsHiss.stop();
|
||||||
fNPress = ( 1 * fNPress + mvOccupied->Handle->GetSound( s_fv4a_u ) ) / ( 2 );
|
|
||||||
if( fNPress > 0 ) {
|
|
||||||
vol = rsHissU.AM * fNPress;
|
|
||||||
}
|
|
||||||
if( vol > 0.001 ) {
|
|
||||||
rsHissU.Play( vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition() );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rsHissU.Stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if( rsHissE.AM != 0 ) // upuszczanie przy naglym
|
// napelnianie PG
|
||||||
{
|
fNPress = interpolate<float>( fNPress, mvOccupied->Handle->GetSound( s_fv4a_u ), 0.25 );
|
||||||
vol = mvOccupied->Handle->GetSound( s_fv4a_e ) * rsHissE.AM;
|
volume = (
|
||||||
if( vol > 0.001 ) {
|
fNPress > 0 ?
|
||||||
rsHissE.Play( vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition() );
|
rsHissU.m_amplitudefactor * fNPress :
|
||||||
}
|
0 );
|
||||||
else {
|
if( volume * brakevolumescale > 0.05 ) {
|
||||||
rsHissE.Stop();
|
rsHissU
|
||||||
}
|
.gain( volume * brakevolumescale )
|
||||||
|
.play( sound_flags::exclusive | sound_flags::looping );
|
||||||
}
|
}
|
||||||
if( rsHissX.AM != 0 ) // upuszczanie sterujacego fala
|
else {
|
||||||
{
|
rsHissU.stop();
|
||||||
vol = mvOccupied->Handle->GetSound( s_fv4a_x ) * rsHissX.AM;
|
|
||||||
if( vol > 0.001 ) {
|
|
||||||
rsHissX.Play( vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition() );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rsHissX.Stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if( rsHissT.AM != 0 ) // upuszczanie z czasowego
|
// upuszczanie przy naglym
|
||||||
{
|
volume = mvOccupied->Handle->GetSound( s_fv4a_e ) * rsHissE.m_amplitudefactor;
|
||||||
vol = mvOccupied->Handle->GetSound( s_fv4a_t ) * rsHissT.AM;
|
if( volume * brakevolumescale > 0.05 ) {
|
||||||
if( vol > 0.001 ) {
|
rsHissE
|
||||||
rsHissT.Play( vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition() );
|
.gain( volume * brakevolumescale )
|
||||||
}
|
.play( sound_flags::exclusive | sound_flags::looping );
|
||||||
else {
|
}
|
||||||
rsHissT.Stop();
|
else {
|
||||||
}
|
rsHissE.stop();
|
||||||
|
}
|
||||||
|
// upuszczanie sterujacego fala
|
||||||
|
volume = mvOccupied->Handle->GetSound( s_fv4a_x ) * rsHissX.m_amplitudefactor;
|
||||||
|
if( volume * brakevolumescale > 0.05 ) {
|
||||||
|
rsHissX
|
||||||
|
.gain( volume * brakevolumescale )
|
||||||
|
.play( sound_flags::exclusive | sound_flags::looping );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rsHissX.stop();
|
||||||
|
}
|
||||||
|
// upuszczanie z czasowego
|
||||||
|
volume = mvOccupied->Handle->GetSound( s_fv4a_t ) * rsHissT.m_amplitudefactor;
|
||||||
|
if( volume * brakevolumescale > 0.05 ) {
|
||||||
|
rsHissT
|
||||||
|
.gain( volume * brakevolumescale )
|
||||||
|
.play( sound_flags::exclusive | sound_flags::looping );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rsHissT.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // koniec FV4a
|
} else {
|
||||||
else // jesli nie FV4a
|
// jesli nie FV4a
|
||||||
{
|
// upuszczanie z PG
|
||||||
if( rsHiss.AM != 0.0 ) // upuszczanie z PG
|
fPPress = ( 4.0f * fPPress + std::max( mvOccupied->dpLocalValve, mvOccupied->dpMainValve ) ) / ( 4.0f + 1.0f );
|
||||||
{
|
volume = (
|
||||||
fPPress = ( 4.0f * fPPress + std::max( mvOccupied->dpLocalValve, mvOccupied->dpMainValve ) ) / ( 4.0f + 1.0f );
|
fPPress > 0.0f ?
|
||||||
if( fPPress > 0.0f ) {
|
2.0 * rsHiss.m_amplitudefactor * fPPress :
|
||||||
vol = 2.0 * rsHiss.AM * fPPress;
|
0.0 );
|
||||||
}
|
if( volume > 0.05 ) {
|
||||||
if( vol > 0.01 ) {
|
rsHiss
|
||||||
rsHiss.Play( vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition() );
|
.gain( volume )
|
||||||
}
|
.play( sound_flags::exclusive | sound_flags::looping );
|
||||||
else {
|
|
||||||
rsHiss.Stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if( rsHissU.AM != 0.0 ) // napelnianie PG
|
else {
|
||||||
{
|
rsHiss.stop();
|
||||||
fNPress = ( 4.0f * fNPress + Min0R( mvOccupied->dpLocalValve, mvOccupied->dpMainValve ) ) / ( 4.0f + 1.0f );
|
}
|
||||||
if( fNPress < 0.0f ) {
|
// napelnianie PG
|
||||||
vol = -1.0 * rsHissU.AM * fNPress;
|
fNPress = ( 4.0f * fNPress + Min0R( mvOccupied->dpLocalValve, mvOccupied->dpMainValve ) ) / ( 4.0f + 1.0f );
|
||||||
}
|
volume = (
|
||||||
if( vol > 0.01 ) {
|
fNPress < 0.0f ?
|
||||||
rsHissU.Play( vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition() );
|
-1.0 * rsHissU.m_amplitudefactor * fNPress :
|
||||||
}
|
0.0 );
|
||||||
else {
|
if( volume > 0.01 ) {
|
||||||
rsHissU.Stop();
|
rsHissU
|
||||||
}
|
.gain( volume )
|
||||||
|
.play( sound_flags::exclusive | sound_flags::looping );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rsHissU.stop();
|
||||||
}
|
}
|
||||||
} // koniec nie FV4a
|
} // koniec nie FV4a
|
||||||
|
|
||||||
// Winger-160404 - syczenie pomocniczego (luzowanie)
|
// Winger-160404 - syczenie pomocniczego (luzowanie)
|
||||||
/* if (rsSBHiss.AM!=0)
|
if( m_lastlocalbrakepressure != -1.f ) {
|
||||||
{
|
// calculate rate of pressure drop in local brake cylinder, once it's been initialized
|
||||||
fSPPress=(mvOccupied->LocalBrakeRatio())-(mvOccupied->LocalBrakePos);
|
auto const brakepressuredifference { m_lastlocalbrakepressure - mvOccupied->LocBrakePress };
|
||||||
if (fSPPress>0)
|
m_localbrakepressurechange = interpolate<float>( m_localbrakepressurechange, 10 * ( brakepressuredifference / Deltatime ), 0.1f );
|
||||||
{
|
}
|
||||||
vol=2*rsSBHiss.AM*fSPPress;
|
m_lastlocalbrakepressure = mvOccupied->LocBrakePress;
|
||||||
}
|
if( ( m_localbrakepressurechange > 0.05f )
|
||||||
if (vol>0.1)
|
&& ( mvOccupied->LocBrakePress > mvOccupied->BrakePress - 0.05 ) ) {
|
||||||
{
|
rsSBHiss
|
||||||
rsSBHiss.Play(vol,DSBPLAY_LOOPING,true,DynamicObject->GetPosition());
|
.gain( clamp( 0.05 * m_localbrakepressurechange, 0.0, 1.5 ) )
|
||||||
}
|
.play( sound_flags::exclusive | sound_flags::looping );
|
||||||
else
|
}
|
||||||
{
|
else {
|
||||||
rsSBHiss.Stop();
|
// don't stop the sound too abruptly
|
||||||
}
|
volume = std::max( 0.0, rsSBHiss.gain() - 0.1 * Deltatime );
|
||||||
}
|
rsSBHiss.gain( volume );
|
||||||
*/
|
if( volume < 0.05 ) {
|
||||||
#endif
|
rsSBHiss.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
|
||||||
@@ -5400,6 +5408,10 @@ bool TTrain::LoadMMediaFile(std::string const &asFileName)
|
|||||||
// syk:
|
// syk:
|
||||||
rsHiss.deserialize( parser, sound_type::single, sound_parameters::amplitude );
|
rsHiss.deserialize( parser, sound_type::single, sound_parameters::amplitude );
|
||||||
rsHiss.owner( DynamicObject );
|
rsHiss.owner( DynamicObject );
|
||||||
|
if( true == rsSBHiss.empty() ) {
|
||||||
|
// fallback for vehicles without defined local brake hiss sound
|
||||||
|
rsSBHiss = rsHiss;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (token == "airsound2:")
|
else if (token == "airsound2:")
|
||||||
{
|
{
|
||||||
|
|||||||
4
Train.h
4
Train.h
@@ -410,6 +410,8 @@ public: // reszta może by?publiczna
|
|||||||
sound_source rsHissX { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // fala
|
sound_source rsHissX { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // fala
|
||||||
sound_source rsHissT { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // czasowy
|
sound_source rsHissT { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // czasowy
|
||||||
sound_source rsSBHiss { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // local
|
sound_source rsSBHiss { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // local
|
||||||
|
float m_lastlocalbrakepressure { -1.f }; // helper, cached level of pressure in local brake cylinder
|
||||||
|
float m_localbrakepressurechange { 0.f }; // recent change of pressure in local brake cylinder
|
||||||
|
|
||||||
sound_source rsFadeSound { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
|
sound_source rsFadeSound { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
|
||||||
sound_source dsbHasler { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
|
sound_source dsbHasler { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
|
||||||
@@ -461,7 +463,7 @@ private:
|
|||||||
bool bHeat[8]; // grzanie
|
bool bHeat[8]; // grzanie
|
||||||
// McZapkie: do syczenia
|
// McZapkie: do syczenia
|
||||||
float fPPress, fNPress;
|
float fPPress, fNPress;
|
||||||
float fSPPress, fSNPress;
|
// float fSPPress, fSNPress;
|
||||||
int iSekunda; // Ra: sekunda aktualizacji pr?dko?ci
|
int iSekunda; // Ra: sekunda aktualizacji pr?dko?ci
|
||||||
int iRadioChannel; // numer aktualnego kana?u radiowego
|
int iRadioChannel; // numer aktualnego kana?u radiowego
|
||||||
TPythonScreens pyScreens;
|
TPythonScreens pyScreens;
|
||||||
|
|||||||
13
audio.cpp
13
audio.cpp
@@ -128,7 +128,18 @@ buffer_manager::create( std::string const &Filename ) {
|
|||||||
return emplace( filelookup );
|
return emplace( filelookup );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if dynamic-specific lookup finds nothing, try the default sound folder
|
if( filename.find( '/' ) != std::string::npos ) {
|
||||||
|
// if the filename includes path, try to use it directly
|
||||||
|
lookup = find_buffer( filename );
|
||||||
|
if( lookup != null_handle ) {
|
||||||
|
return lookup;
|
||||||
|
}
|
||||||
|
filelookup = find_file( filename );
|
||||||
|
if( false == filelookup.empty() ) {
|
||||||
|
return emplace( filelookup );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if dynamic-specific and/or direct lookups find nothing, try the default sound folder
|
||||||
lookup = find_buffer( szSoundPath + filename );
|
lookup = find_buffer( szSoundPath + filename );
|
||||||
if( lookup != null_handle ) {
|
if( lookup != null_handle ) {
|
||||||
return lookup;
|
return lookup;
|
||||||
|
|||||||
@@ -33,6 +33,12 @@ void
|
|||||||
openal_source::stop() {
|
openal_source::stop() {
|
||||||
|
|
||||||
loop( false );
|
loop( false );
|
||||||
|
// NOTE: workaround for potential edge cases where ::alSourceStop() doesn't set source which wasn't yet started to AL_STOPPED
|
||||||
|
int state;
|
||||||
|
::alGetSourcei( id, AL_SOURCE_STATE, &state );
|
||||||
|
if( state == AL_INITIAL ) {
|
||||||
|
play();
|
||||||
|
}
|
||||||
::alSourceStop( id );
|
::alSourceStop( id );
|
||||||
is_playing = false;
|
is_playing = false;
|
||||||
}
|
}
|
||||||
@@ -43,7 +49,6 @@ openal_source::update( double const Deltatime ) {
|
|||||||
|
|
||||||
update_deltatime = Deltatime; // cached for time-based processing of data from the controller
|
update_deltatime = Deltatime; // cached for time-based processing of data from the controller
|
||||||
|
|
||||||
// TODO: test whether the emitter was within range during the last tick, potentially update the counter and flag it for timeout
|
|
||||||
::alGetSourcei( id, AL_BUFFERS_PROCESSED, &buffer_index );
|
::alGetSourcei( id, AL_BUFFERS_PROCESSED, &buffer_index );
|
||||||
// for multipart sounds trim away processed sources until only one remains, the last one may be set to looping by the controller
|
// for multipart sounds trim away processed sources until only one remains, the last one may be set to looping by the controller
|
||||||
ALuint bufferid;
|
ALuint bufferid;
|
||||||
@@ -53,9 +58,11 @@ openal_source::update( double const Deltatime ) {
|
|||||||
buffers.erase( std::begin( buffers ) );
|
buffers.erase( std::begin( buffers ) );
|
||||||
--buffer_index;
|
--buffer_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
int state;
|
int state;
|
||||||
::alGetSourcei( id, AL_SOURCE_STATE, &state );
|
::alGetSourcei( id, AL_SOURCE_STATE, &state );
|
||||||
is_playing = ( state == AL_PLAYING );
|
is_playing = ( state == AL_PLAYING );
|
||||||
|
|
||||||
// request instructions from the controller
|
// request instructions from the controller
|
||||||
controller->update( *this );
|
controller->update( *this );
|
||||||
}
|
}
|
||||||
@@ -75,6 +82,7 @@ openal_source::sync_with( sound_properties const &State ) {
|
|||||||
if( glm::length2( sourceoffset ) > std::max( ( sound_range * sound_range ), ( EU07_SOUND_CUTOFFRANGE * EU07_SOUND_CUTOFFRANGE ) ) ) {
|
if( glm::length2( sourceoffset ) > std::max( ( sound_range * sound_range ), ( EU07_SOUND_CUTOFFRANGE * EU07_SOUND_CUTOFFRANGE ) ) ) {
|
||||||
// range cutoff check
|
// range cutoff check
|
||||||
stop();
|
stop();
|
||||||
|
is_synced = false; // flag sync failure for the controller
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if( sound_range >= 0 ) {
|
if( sound_range >= 0 ) {
|
||||||
@@ -101,6 +109,7 @@ openal_source::sync_with( sound_properties const &State ) {
|
|||||||
|
|
||||||
::alSourcef( id, AL_PITCH, properties.base_pitch * pitch_variation );
|
::alSourcef( id, AL_PITCH, properties.base_pitch * pitch_variation );
|
||||||
}
|
}
|
||||||
|
is_synced = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets max audible distance for sounds emitted by the source
|
// sets max audible distance for sounds emitted by the source
|
||||||
@@ -145,20 +154,18 @@ openal_source::loop( bool const State ) {
|
|||||||
// NOTE: doesn't release allocated implementation-side source
|
// NOTE: doesn't release allocated implementation-side source
|
||||||
void
|
void
|
||||||
openal_source::clear() {
|
openal_source::clear() {
|
||||||
|
|
||||||
controller = nullptr;
|
|
||||||
// unqueue bound buffers:
|
// unqueue bound buffers:
|
||||||
// ensure no buffer is in use...
|
// ensure no buffer is in use...
|
||||||
stop();
|
stop();
|
||||||
// ...prepare space for returned ids of unqueued buffers (not that we need that info)...
|
// ...prepare space for returned ids of unqueued buffers (not that we need that info)...
|
||||||
std::vector<ALuint> bufferids;
|
std::vector<ALuint> bufferids;
|
||||||
bufferids.resize( buffers.size() );
|
bufferids.resize( buffers.size() );
|
||||||
// ...release the buffers and update source data to match
|
// ...release the buffers...
|
||||||
::alSourceUnqueueBuffers( id, bufferids.size(), bufferids.data() );
|
::alSourceUnqueueBuffers( id, bufferids.size(), bufferids.data() );
|
||||||
buffers.clear();
|
// ...and reset reset the properties, except for the id of the allocated source
|
||||||
buffer_index = 0;
|
auto const sourceid { id };
|
||||||
// reset properties
|
*this = openal_source();
|
||||||
properties = sound_properties();
|
id = sourceid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -36,9 +36,10 @@ struct openal_source {
|
|||||||
ALuint id { audio::null_resource }; // associated AL resource
|
ALuint id { audio::null_resource }; // associated AL resource
|
||||||
sound_source *controller { nullptr }; // source controller
|
sound_source *controller { nullptr }; // source controller
|
||||||
buffer_sequence buffers; // sequence of samples the source will emit
|
buffer_sequence buffers; // sequence of samples the source will emit
|
||||||
int buffer_index; // currently queued sample from the buffer sequence
|
int buffer_index { 0 }; // currently queued sample from the buffer sequence
|
||||||
bool is_playing { false };
|
bool is_playing { false };
|
||||||
bool is_looping { false };
|
bool is_looping { false };
|
||||||
|
bool is_synced { true }; // set to false only if a sync attempt fails
|
||||||
sound_properties properties;
|
sound_properties properties;
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
|
|||||||
50
sound.cpp
50
sound.cpp
@@ -108,10 +108,10 @@ sound_source::play( int const Flags ) {
|
|||||||
// TODO: support for parameter-driven sound table
|
// TODO: support for parameter-driven sound table
|
||||||
if( m_soundbegin.buffer != null_handle ) {
|
if( m_soundbegin.buffer != null_handle ) {
|
||||||
std::vector<audio::buffer_handle> bufferlist { m_soundbegin.buffer, m_soundmain.buffer };
|
std::vector<audio::buffer_handle> bufferlist { m_soundbegin.buffer, m_soundmain.buffer };
|
||||||
audio::renderer.insert( this, std::begin( bufferlist ), std::end( bufferlist ) );
|
insert( std::begin( bufferlist ), std::end( bufferlist ) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
audio::renderer.insert( this, m_soundmain.buffer );
|
insert( m_soundmain.buffer );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -119,7 +119,7 @@ sound_source::play( int const Flags ) {
|
|||||||
if( ( m_soundbegin.buffer == null_handle )
|
if( ( m_soundbegin.buffer == null_handle )
|
||||||
&& ( ( m_flags & ( sound_flags::exclusive | sound_flags::looping ) ) == 0 ) ) {
|
&& ( ( m_flags & ( sound_flags::exclusive | sound_flags::looping ) ) == 0 ) ) {
|
||||||
// for single part non-looping samples we allow spawning multiple instances, if not prevented by set flags
|
// for single part non-looping samples we allow spawning multiple instances, if not prevented by set flags
|
||||||
audio::renderer.insert( this, m_soundmain.buffer );
|
insert( m_soundmain.buffer );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ sound_source::stop() {
|
|||||||
if( ( m_soundend.buffer != null_handle )
|
if( ( m_soundend.buffer != null_handle )
|
||||||
&& ( m_soundend.buffer != m_soundmain.buffer ) ) { // end == main can happen in malformed legacy cases
|
&& ( m_soundend.buffer != m_soundmain.buffer ) ) { // end == main can happen in malformed legacy cases
|
||||||
// spawn potentially defined sound end sample, if the emitter is currently active
|
// spawn potentially defined sound end sample, if the emitter is currently active
|
||||||
audio::renderer.insert( this, m_soundend.buffer );
|
insert( m_soundend.buffer );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,10 +154,6 @@ sound_source::update( audio::openal_source &Source ) {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// check and update if needed current sound properties
|
|
||||||
update_location();
|
|
||||||
update_placement_gain();
|
|
||||||
Source.sync_with( m_properties );
|
|
||||||
|
|
||||||
if( m_soundbegin.buffer != null_handle ) {
|
if( m_soundbegin.buffer != null_handle ) {
|
||||||
// potentially a multipart sound
|
// potentially a multipart sound
|
||||||
@@ -170,26 +166,41 @@ sound_source::update( audio::openal_source &Source ) {
|
|||||||
++( m_soundmain.playing );
|
++( m_soundmain.playing );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check and update if needed current sound properties
|
||||||
|
update_location();
|
||||||
|
update_placement_gain();
|
||||||
|
Source.sync_with( m_properties );
|
||||||
|
if( false == Source.is_synced ) {
|
||||||
|
// if the sync went wrong we let the renderer kill its part of the emitter, and update our playcounter(s) to match
|
||||||
|
update_counter( Source.buffers[ Source.buffer_index ], -1 );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// if the emitter isn't playing it's either done or wasn't yet started
|
// if the emitter isn't playing it's either done or wasn't yet started
|
||||||
// we can determine this from number of processed buffers
|
// we can determine this from number of processed buffers
|
||||||
if( Source.buffer_index != Source.buffers.size() ) {
|
if( Source.buffer_index != Source.buffers.size() ) {
|
||||||
auto const buffer { Source.buffers[ Source.buffer_index ] };
|
auto const buffer { Source.buffers[ Source.buffer_index ] };
|
||||||
update_counter( buffer, 1 );
|
|
||||||
// emitter initialization
|
// emitter initialization
|
||||||
Source.range( m_range );
|
|
||||||
Source.pitch( m_pitchvariation );
|
|
||||||
update_location();
|
|
||||||
update_placement_gain();
|
|
||||||
Source.sync_with( m_properties );
|
|
||||||
if( ( buffer == m_soundmain.buffer )
|
if( ( buffer == m_soundmain.buffer )
|
||||||
&& ( true == TestFlag( m_flags, sound_flags::looping ) ) ) {
|
&& ( true == TestFlag( m_flags, sound_flags::looping ) ) ) {
|
||||||
// main sample can be optionally set to loop
|
// main sample can be optionally set to loop
|
||||||
Source.loop( true );
|
Source.loop( true );
|
||||||
}
|
}
|
||||||
// all set, start playback
|
Source.range( m_range );
|
||||||
Source.play();
|
Source.pitch( m_pitchvariation );
|
||||||
|
update_location();
|
||||||
|
update_placement_gain();
|
||||||
|
Source.sync_with( m_properties );
|
||||||
|
if( true == Source.is_synced ) {
|
||||||
|
// all set, start playback
|
||||||
|
Source.play();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// if the initial sync went wrong we skip the activation so the renderer can clean the emitter on its end
|
||||||
|
update_counter( buffer, -1 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto const buffer { Source.buffers[ Source.buffer_index - 1 ] };
|
auto const buffer { Source.buffers[ Source.buffer_index - 1 ] };
|
||||||
@@ -339,4 +350,11 @@ sound_source::update_placement_gain() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sound_source::insert( audio::buffer_handle Buffer ) {
|
||||||
|
|
||||||
|
std::vector<audio::buffer_handle> buffers { Buffer };
|
||||||
|
return insert( std::begin( buffers ), std::end( buffers ) );
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|||||||
11
sound.h
11
sound.h
@@ -15,7 +15,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
float const EU07_SOUND_CABCONTROLSCUTOFFRANGE { 7.5f };
|
float const EU07_SOUND_CABCONTROLSCUTOFFRANGE { 7.5f };
|
||||||
float const EU07_SOUND_BRAKINGCUTOFFRANGE { 100.f };
|
float const EU07_SOUND_BRAKINGCUTOFFRANGE { 100.f };
|
||||||
float const EU07_SOUND_RUNNINGNOISECUTOFFRANGE { 100.f };
|
float const EU07_SOUND_RUNNINGNOISECUTOFFRANGE { 200.f };
|
||||||
|
|
||||||
enum class sound_type {
|
enum class sound_type {
|
||||||
single,
|
single,
|
||||||
@@ -122,6 +122,15 @@ private:
|
|||||||
// potentially updates area-based gain factor of the source. returns: true if location has changed
|
// potentially updates area-based gain factor of the source. returns: true if location has changed
|
||||||
bool
|
bool
|
||||||
update_placement_gain();
|
update_placement_gain();
|
||||||
|
void
|
||||||
|
insert( audio::buffer_handle Buffer );
|
||||||
|
template <class Iterator_>
|
||||||
|
void
|
||||||
|
insert( Iterator_ First, Iterator_ Last ) {
|
||||||
|
|
||||||
|
audio::renderer.insert( this, First, Last );
|
||||||
|
update_counter( *First, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
// members
|
// members
|
||||||
TDynamicObject const * m_owner { nullptr }; // optional, the vehicle carrying this sound source
|
TDynamicObject const * m_owner { nullptr }; // optional, the vehicle carrying this sound source
|
||||||
|
|||||||
Reference in New Issue
Block a user