mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-18 03:09:18 +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)
|
||||
{ // jeśli drzwi sterowane z kabiny
|
||||
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 )
|
||||
&& ( false == mvOccupied->DepartureSignal )
|
||||
&& ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) {
|
||||
@@ -3092,8 +3093,8 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
|
||||
asNextStop = TrainParams->NextStop();
|
||||
iDrivigFlags |= movePrimary; // skoro dostał rozkład, to jest teraz głównym
|
||||
NewCommand = Global::asCurrentSceneryPath + NewCommand + ".wav"; // na razie jeden
|
||||
if (FileExists(NewCommand))
|
||||
{ // wczytanie dźwięku odjazdu podawanego bezpośrenido
|
||||
if (FileExists(NewCommand)) {
|
||||
// wczytanie dźwięku odjazdu podawanego bezpośrenido
|
||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||
tsGuardSignal =
|
||||
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,
|
||||
false);
|
||||
#else
|
||||
tsGuardSignal = new sound_source( sound_placement::external );
|
||||
tsGuardSignal = new sound_source( sound_placement::external, 75.f );
|
||||
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
|
||||
iGuardRadio = 0; // nie przez radio
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
NewCommand = NewCommand.insert(NewCommand.find_last_of("."),"radio"); // wstawienie przed kropkč
|
||||
if (FileExists(NewCommand))
|
||||
{ // wczytanie dźwięku odjazdu w wersji radiowej (słychać tylko w kabinie)
|
||||
if (FileExists(NewCommand)) {
|
||||
// wczytanie dźwięku odjazdu w wersji radiowej (słychać tylko w kabinie)
|
||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||
tsGuardSignal =
|
||||
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,
|
||||
false);
|
||||
#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->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
|
||||
iGuardRadio = iRadioChannel;
|
||||
}
|
||||
@@ -4487,20 +4480,21 @@ TController::UpdateSituation(double dt) {
|
||||
}
|
||||
if (VelDesired > 0.0)
|
||||
if( ( ( iDrivigFlags & moveStopHere ) == 0 )
|
||||
|| ( ( SemNextIndex != -1 )
|
||||
&& ( SemNextIndex < sSpeedTable.size() ) // BUG: index can point at non-existing slot. investigate reason(s)
|
||||
&& ( sSpeedTable[SemNextIndex].fVelNext != 0.0 ) ) ) {
|
||||
|| ( ( SemNextIndex != -1 )
|
||||
&& ( SemNextIndex < sSpeedTable.size() ) // BUG: index can point at non-existing slot. investigate reason(s)
|
||||
&& ( sSpeedTable[SemNextIndex].fVelNext != 0.0 ) ) ) {
|
||||
// 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ć
|
||||
if (iDrivigFlags & moveGuardSignal)
|
||||
{ // komunikat od kierownika tu, bo musi być wolna droga i odczekany czas stania
|
||||
iDrivigFlags &= ~moveGuardSignal; // tylko raz nadać
|
||||
|
||||
/*
|
||||
if( ( iDrivigFlags & moveDoorOpened )
|
||||
&& ( false == mvOccupied->DoorOpenCtrl ) ) {
|
||||
// jeśli drzwi otwarte, niesterowane przez maszynistę
|
||||
Doors( false ); // a EZT zamknie dopiero po odegraniu komunikatu kierownika
|
||||
}
|
||||
*/
|
||||
if( tsGuardSignal != nullptr ) {
|
||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||
tsGuardSignal->Stop();
|
||||
@@ -4513,11 +4507,14 @@ TController::UpdateSituation(double dt) {
|
||||
// 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ć
|
||||
// obsługę kanałów radiowych itd.
|
||||
if( !iGuardRadio ) {
|
||||
if( iGuardRadio == 0 ) {
|
||||
// jeśli nie przez radio
|
||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||
tsGuardSignal->Play( 1.0, 0, !FreeFlyModeFlag, pVehicle->GetPosition() ); // dla true jest głośniej
|
||||
#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 );
|
||||
#endif
|
||||
}
|
||||
@@ -4526,15 +4523,18 @@ TController::UpdateSituation(double dt) {
|
||||
// if (!FreeFlyModeFlag) //obserwator musi być w środku pojazdu
|
||||
// (albo może mieć radio przenośne) - kierownik mógłby powtarzać
|
||||
// przy braku reakcji
|
||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||
if( SquareMagnitude( pVehicle->GetPosition() - Global::pCameraPosition ) < 2000 * 2000 ) {
|
||||
// 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
|
||||
#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 const dt { Timer::GetDeltaRenderTime() };
|
||||
|
||||
if( dt == 0.0 ) { return; }
|
||||
|
||||
// engine sounds
|
||||
if( MoverParameters->Power > 0 ) {
|
||||
|
||||
@@ -3889,7 +3891,7 @@ void TDynamicObject::RenderSounds() {
|
||||
}
|
||||
else {
|
||||
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 ) {
|
||||
sTurbo
|
||||
.pitch( 0.4 + eng_turbo * 0.4 )
|
||||
@@ -3943,7 +3945,7 @@ void TDynamicObject::RenderSounds() {
|
||||
|
||||
// brake system and braking sounds:
|
||||
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 };
|
||||
m_brakepressurechange = interpolate<float>( m_brakepressurechange, 10 * ( brakepressuredifference / dt ), 0.1f );
|
||||
}
|
||||
@@ -3951,7 +3953,7 @@ void TDynamicObject::RenderSounds() {
|
||||
if( m_brakepressurechange > 0.05f ) {
|
||||
// NOTE: can't use the leak rate directly due to irregular results produced by some brake type implementations
|
||||
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 );
|
||||
}
|
||||
else {
|
||||
@@ -4164,13 +4166,13 @@ void TDynamicObject::RenderSounds() {
|
||||
}
|
||||
// scale volume by track quality
|
||||
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?
|
||||
volume *=
|
||||
interpolate(
|
||||
0.0, 1.0,
|
||||
clamp(
|
||||
MoverParameters->Vel / 80.0,
|
||||
MoverParameters->Vel / 60.0,
|
||||
0.0, 1.0 ) );
|
||||
rsRunningNoise
|
||||
.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
|
||||
TTrain::update_sounds( double const Deltatime ) {
|
||||
#ifdef EU07_USE_OLD_SOUNDCODE
|
||||
double vol = 0;
|
||||
// int freq=1;
|
||||
double dfreq;
|
||||
|
||||
if( Deltatime == 0.0 ) { return; }
|
||||
|
||||
double volume { 0.0 };
|
||||
double const brakevolumescale { 0.5 };
|
||||
|
||||
// McZapkie-280302 - syczenie
|
||||
if( ( mvOccupied->BrakeHandle == FV4a ) || ( mvOccupied->BrakeHandle == FVel6 ) ) {
|
||||
if( rsHiss.AM != 0 ) // upuszczanie z PG
|
||||
{
|
||||
fPPress = ( 1 * fPPress + mvOccupied->Handle->GetSound( s_fv4a_b ) ) / ( 2 );
|
||||
if( fPPress > 0 ) {
|
||||
vol = 2.0 * rsHiss.AM * fPPress;
|
||||
}
|
||||
if( vol > 0.001 ) {
|
||||
rsHiss.Play( vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition() );
|
||||
}
|
||||
else {
|
||||
rsHiss.Stop();
|
||||
}
|
||||
// TODO: softer volume reduction than plain abrupt stop, perhaps as reusable wrapper?
|
||||
if( ( mvOccupied->BrakeHandle == FV4a )
|
||||
|| ( mvOccupied->BrakeHandle == FVel6 ) ) {
|
||||
// upuszczanie z PG
|
||||
fPPress = interpolate<float>( fPPress, mvOccupied->Handle->GetSound( s_fv4a_b ), 0.05 );
|
||||
volume = (
|
||||
fPPress > 0 ?
|
||||
rsHiss.m_amplitudefactor * fPPress * 0.25 :
|
||||
0 );
|
||||
if( volume * brakevolumescale > 0.05 ) {
|
||||
rsHiss
|
||||
.gain( volume * brakevolumescale )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
}
|
||||
if( rsHissU.AM != 0 ) // upuszczanie z PG
|
||||
{
|
||||
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();
|
||||
}
|
||||
else {
|
||||
rsHiss.stop();
|
||||
}
|
||||
if( rsHissE.AM != 0 ) // upuszczanie przy naglym
|
||||
{
|
||||
vol = mvOccupied->Handle->GetSound( s_fv4a_e ) * rsHissE.AM;
|
||||
if( vol > 0.001 ) {
|
||||
rsHissE.Play( vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition() );
|
||||
}
|
||||
else {
|
||||
rsHissE.Stop();
|
||||
}
|
||||
// napelnianie PG
|
||||
fNPress = interpolate<float>( fNPress, mvOccupied->Handle->GetSound( s_fv4a_u ), 0.25 );
|
||||
volume = (
|
||||
fNPress > 0 ?
|
||||
rsHissU.m_amplitudefactor * fNPress :
|
||||
0 );
|
||||
if( volume * brakevolumescale > 0.05 ) {
|
||||
rsHissU
|
||||
.gain( volume * brakevolumescale )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
}
|
||||
if( rsHissX.AM != 0 ) // upuszczanie sterujacego fala
|
||||
{
|
||||
vol = mvOccupied->Handle->GetSound( s_fv4a_x ) * rsHissX.AM;
|
||||
if( vol > 0.001 ) {
|
||||
rsHissX.Play( vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition() );
|
||||
}
|
||||
else {
|
||||
rsHissX.Stop();
|
||||
}
|
||||
else {
|
||||
rsHissU.stop();
|
||||
}
|
||||
if( rsHissT.AM != 0 ) // upuszczanie z czasowego
|
||||
{
|
||||
vol = mvOccupied->Handle->GetSound( s_fv4a_t ) * rsHissT.AM;
|
||||
if( vol > 0.001 ) {
|
||||
rsHissT.Play( vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition() );
|
||||
}
|
||||
else {
|
||||
rsHissT.Stop();
|
||||
}
|
||||
// upuszczanie przy naglym
|
||||
volume = mvOccupied->Handle->GetSound( s_fv4a_e ) * rsHissE.m_amplitudefactor;
|
||||
if( volume * brakevolumescale > 0.05 ) {
|
||||
rsHissE
|
||||
.gain( volume * brakevolumescale )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
}
|
||||
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 // jesli nie FV4a
|
||||
{
|
||||
if( rsHiss.AM != 0.0 ) // upuszczanie z PG
|
||||
{
|
||||
fPPress = ( 4.0f * fPPress + std::max( mvOccupied->dpLocalValve, mvOccupied->dpMainValve ) ) / ( 4.0f + 1.0f );
|
||||
if( fPPress > 0.0f ) {
|
||||
vol = 2.0 * rsHiss.AM * fPPress;
|
||||
}
|
||||
if( vol > 0.01 ) {
|
||||
rsHiss.Play( vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition() );
|
||||
}
|
||||
else {
|
||||
rsHiss.Stop();
|
||||
}
|
||||
} else {
|
||||
// jesli nie FV4a
|
||||
// upuszczanie z PG
|
||||
fPPress = ( 4.0f * fPPress + std::max( mvOccupied->dpLocalValve, mvOccupied->dpMainValve ) ) / ( 4.0f + 1.0f );
|
||||
volume = (
|
||||
fPPress > 0.0f ?
|
||||
2.0 * rsHiss.m_amplitudefactor * fPPress :
|
||||
0.0 );
|
||||
if( volume > 0.05 ) {
|
||||
rsHiss
|
||||
.gain( volume )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
}
|
||||
if( rsHissU.AM != 0.0 ) // napelnianie PG
|
||||
{
|
||||
fNPress = ( 4.0f * fNPress + Min0R( mvOccupied->dpLocalValve, mvOccupied->dpMainValve ) ) / ( 4.0f + 1.0f );
|
||||
if( fNPress < 0.0f ) {
|
||||
vol = -1.0 * rsHissU.AM * fNPress;
|
||||
}
|
||||
if( vol > 0.01 ) {
|
||||
rsHissU.Play( vol, DSBPLAY_LOOPING, true, DynamicObject->GetPosition() );
|
||||
}
|
||||
else {
|
||||
rsHissU.Stop();
|
||||
}
|
||||
else {
|
||||
rsHiss.stop();
|
||||
}
|
||||
// napelnianie PG
|
||||
fNPress = ( 4.0f * fNPress + Min0R( mvOccupied->dpLocalValve, mvOccupied->dpMainValve ) ) / ( 4.0f + 1.0f );
|
||||
volume = (
|
||||
fNPress < 0.0f ?
|
||||
-1.0 * rsHissU.m_amplitudefactor * fNPress :
|
||||
0.0 );
|
||||
if( volume > 0.01 ) {
|
||||
rsHissU
|
||||
.gain( volume )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
}
|
||||
else {
|
||||
rsHissU.stop();
|
||||
}
|
||||
} // koniec nie FV4a
|
||||
|
||||
// Winger-160404 - syczenie pomocniczego (luzowanie)
|
||||
/* if (rsSBHiss.AM!=0)
|
||||
{
|
||||
fSPPress=(mvOccupied->LocalBrakeRatio())-(mvOccupied->LocalBrakePos);
|
||||
if (fSPPress>0)
|
||||
{
|
||||
vol=2*rsSBHiss.AM*fSPPress;
|
||||
}
|
||||
if (vol>0.1)
|
||||
{
|
||||
rsSBHiss.Play(vol,DSBPLAY_LOOPING,true,DynamicObject->GetPosition());
|
||||
}
|
||||
else
|
||||
{
|
||||
rsSBHiss.Stop();
|
||||
}
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
if( m_lastlocalbrakepressure != -1.f ) {
|
||||
// calculate rate of pressure drop in local brake cylinder, once it's been initialized
|
||||
auto const brakepressuredifference { m_lastlocalbrakepressure - mvOccupied->LocBrakePress };
|
||||
m_localbrakepressurechange = interpolate<float>( m_localbrakepressurechange, 10 * ( brakepressuredifference / Deltatime ), 0.1f );
|
||||
}
|
||||
m_lastlocalbrakepressure = mvOccupied->LocBrakePress;
|
||||
if( ( m_localbrakepressurechange > 0.05f )
|
||||
&& ( mvOccupied->LocBrakePress > mvOccupied->BrakePress - 0.05 ) ) {
|
||||
rsSBHiss
|
||||
.gain( clamp( 0.05 * m_localbrakepressurechange, 0.0, 1.5 ) )
|
||||
.play( sound_flags::exclusive | sound_flags::looping );
|
||||
}
|
||||
else {
|
||||
// don't stop the sound too abruptly
|
||||
volume = std::max( 0.0, rsSBHiss.gain() - 0.1 * Deltatime );
|
||||
rsSBHiss.gain( volume );
|
||||
if( volume < 0.05 ) {
|
||||
rsSBHiss.stop();
|
||||
}
|
||||
}
|
||||
|
||||
// ambient sound
|
||||
// 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:
|
||||
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
|
||||
rsSBHiss = rsHiss;
|
||||
}
|
||||
}
|
||||
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 rsHissT { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // czasowy
|
||||
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 dsbHasler { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
|
||||
@@ -461,7 +463,7 @@ private:
|
||||
bool bHeat[8]; // grzanie
|
||||
// McZapkie: do syczenia
|
||||
float fPPress, fNPress;
|
||||
float fSPPress, fSNPress;
|
||||
// float fSPPress, fSNPress;
|
||||
int iSekunda; // Ra: sekunda aktualizacji pr?dko?ci
|
||||
int iRadioChannel; // numer aktualnego kana?u radiowego
|
||||
TPythonScreens pyScreens;
|
||||
|
||||
13
audio.cpp
13
audio.cpp
@@ -128,7 +128,18 @@ buffer_manager::create( std::string const &Filename ) {
|
||||
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 );
|
||||
if( lookup != null_handle ) {
|
||||
return lookup;
|
||||
|
||||
@@ -33,6 +33,12 @@ void
|
||||
openal_source::stop() {
|
||||
|
||||
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 );
|
||||
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
|
||||
|
||||
// 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 );
|
||||
// for multipart sounds trim away processed sources until only one remains, the last one may be set to looping by the controller
|
||||
ALuint bufferid;
|
||||
@@ -53,9 +58,11 @@ openal_source::update( double const Deltatime ) {
|
||||
buffers.erase( std::begin( buffers ) );
|
||||
--buffer_index;
|
||||
}
|
||||
|
||||
int state;
|
||||
::alGetSourcei( id, AL_SOURCE_STATE, &state );
|
||||
is_playing = ( state == AL_PLAYING );
|
||||
|
||||
// request instructions from the controller
|
||||
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 ) ) ) {
|
||||
// range cutoff check
|
||||
stop();
|
||||
is_synced = false; // flag sync failure for the controller
|
||||
return;
|
||||
}
|
||||
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 );
|
||||
}
|
||||
is_synced = true;
|
||||
}
|
||||
|
||||
// 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
|
||||
void
|
||||
openal_source::clear() {
|
||||
|
||||
controller = nullptr;
|
||||
// unqueue bound buffers:
|
||||
// ensure no buffer is in use...
|
||||
stop();
|
||||
// ...prepare space for returned ids of unqueued buffers (not that we need that info)...
|
||||
std::vector<ALuint> bufferids;
|
||||
bufferids.resize( buffers.size() );
|
||||
// ...release the buffers and update source data to match
|
||||
// ...release the buffers...
|
||||
::alSourceUnqueueBuffers( id, bufferids.size(), bufferids.data() );
|
||||
buffers.clear();
|
||||
buffer_index = 0;
|
||||
// reset properties
|
||||
properties = sound_properties();
|
||||
// ...and reset reset the properties, except for the id of the allocated source
|
||||
auto const sourceid { id };
|
||||
*this = openal_source();
|
||||
id = sourceid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -36,9 +36,10 @@ struct openal_source {
|
||||
ALuint id { audio::null_resource }; // associated AL resource
|
||||
sound_source *controller { nullptr }; // source controller
|
||||
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_looping { false };
|
||||
bool is_synced { true }; // set to false only if a sync attempt fails
|
||||
sound_properties properties;
|
||||
|
||||
// methods
|
||||
|
||||
50
sound.cpp
50
sound.cpp
@@ -108,10 +108,10 @@ sound_source::play( int const Flags ) {
|
||||
// TODO: support for parameter-driven sound table
|
||||
if( m_soundbegin.buffer != null_handle ) {
|
||||
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 {
|
||||
audio::renderer.insert( this, m_soundmain.buffer );
|
||||
insert( m_soundmain.buffer );
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -119,7 +119,7 @@ sound_source::play( int const Flags ) {
|
||||
if( ( m_soundbegin.buffer == null_handle )
|
||||
&& ( ( 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
|
||||
audio::renderer.insert( this, m_soundmain.buffer );
|
||||
insert( m_soundmain.buffer );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,7 @@ sound_source::stop() {
|
||||
if( ( m_soundend.buffer != null_handle )
|
||||
&& ( 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
|
||||
audio::renderer.insert( this, m_soundend.buffer );
|
||||
insert( m_soundend.buffer );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,10 +154,6 @@ sound_source::update( audio::openal_source &Source ) {
|
||||
}
|
||||
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 ) {
|
||||
// potentially a multipart sound
|
||||
@@ -170,26 +166,41 @@ sound_source::update( audio::openal_source &Source ) {
|
||||
++( 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 {
|
||||
// if the emitter isn't playing it's either done or wasn't yet started
|
||||
// we can determine this from number of processed buffers
|
||||
if( Source.buffer_index != Source.buffers.size() ) {
|
||||
auto const buffer { Source.buffers[ Source.buffer_index ] };
|
||||
update_counter( buffer, 1 );
|
||||
// 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 )
|
||||
&& ( true == TestFlag( m_flags, sound_flags::looping ) ) ) {
|
||||
// main sample can be optionally set to loop
|
||||
Source.loop( true );
|
||||
}
|
||||
// all set, start playback
|
||||
Source.play();
|
||||
Source.range( m_range );
|
||||
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 {
|
||||
auto const buffer { Source.buffers[ Source.buffer_index - 1 ] };
|
||||
@@ -339,4 +350,11 @@ sound_source::update_placement_gain() {
|
||||
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_BRAKINGCUTOFFRANGE { 100.f };
|
||||
float const EU07_SOUND_RUNNINGNOISECUTOFFRANGE { 100.f };
|
||||
float const EU07_SOUND_RUNNINGNOISECUTOFFRANGE { 200.f };
|
||||
|
||||
enum class sound_type {
|
||||
single,
|
||||
@@ -122,6 +122,15 @@ private:
|
||||
// potentially updates area-based gain factor of the source. returns: true if location has changed
|
||||
bool
|
||||
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
|
||||
TDynamicObject const * m_owner { nullptr }; // optional, the vehicle carrying this sound source
|
||||
|
||||
Reference in New Issue
Block a user