mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 23:19:19 +02:00
build 171205. support for random sound sets, explicit range-driven sound attenuation
This commit is contained in:
21
DynObj.cpp
21
DynObj.cpp
@@ -16,6 +16,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "DynObj.h"
|
#include "DynObj.h"
|
||||||
|
|
||||||
#include "simulation.h"
|
#include "simulation.h"
|
||||||
|
#include "train.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
#include "logs.h"
|
#include "logs.h"
|
||||||
@@ -3811,7 +3812,6 @@ void TDynamicObject::RenderSounds() {
|
|||||||
// eng_frq_act=eng_frq;
|
// eng_frq_act=eng_frq;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if( ( MoverParameters->EngineType == ElectricSeriesMotor )
|
if( ( MoverParameters->EngineType == ElectricSeriesMotor )
|
||||||
|| ( MoverParameters->EngineType == ElectricInductionMotor ) ) {
|
|| ( MoverParameters->EngineType == ElectricInductionMotor ) ) {
|
||||||
|
|
||||||
@@ -4009,8 +4009,8 @@ void TDynamicObject::RenderSounds() {
|
|||||||
sSand.stop();
|
sSand.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( /*( false == mvOccupied->SlippingWheels )
|
if( //( false == mvOccupied->SlippingWheels ) &&
|
||||||
&&*/ ( MoverParameters->UnitBrakeForce > 10.0 )
|
( MoverParameters->UnitBrakeForce > 10.0 )
|
||||||
&& ( GetVelocity() > 0.05 ) ) {
|
&& ( GetVelocity() > 0.05 ) ) {
|
||||||
|
|
||||||
rsBrake
|
rsBrake
|
||||||
@@ -4030,8 +4030,8 @@ void TDynamicObject::RenderSounds() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// McZapkie-280302 - pisk mocno zacisnietych hamulcow
|
// McZapkie-280302 - pisk mocno zacisnietych hamulcow
|
||||||
if( /*( false == MoverParameters->SlippingWheels )
|
if( //( false == MoverParameters->SlippingWheels ) &&
|
||||||
&&*/ ( MoverParameters->UnitBrakeForce > rsPisk.m_amplitudefactor )
|
( MoverParameters->UnitBrakeForce > rsPisk.m_amplitudefactor )
|
||||||
&& ( MoverParameters->Vel > 2.5 ) ) {
|
&& ( MoverParameters->Vel > 2.5 ) ) {
|
||||||
|
|
||||||
rsPisk
|
rsPisk
|
||||||
@@ -4118,7 +4118,13 @@ void TDynamicObject::RenderSounds() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// szum w czasie jazdy
|
// szum w czasie jazdy
|
||||||
if( GetVelocity() > 0.5 ) {
|
if( ( GetVelocity() > 0.5 )
|
||||||
|
&& ( // compound test whether the vehicle belongs to user-driven consist (as these don't emit outer noise in cab view)
|
||||||
|
true == FreeFlyModeFlag ? true : // in external view all vehicles emit outer noise
|
||||||
|
// Global::pWorld->train() == nullptr ? true : // (can skip this check, with no player train the external view is a given)
|
||||||
|
ctOwner == nullptr ? true : // standalone vehicle, can't be part of user-driven train
|
||||||
|
ctOwner != Global::pWorld->train()->Dynamic()->ctOwner ? true : // confirmed isn't a part of the user-driven train
|
||||||
|
false ) ) {
|
||||||
|
|
||||||
volume = rsOuterNoise.m_amplitudefactor * MoverParameters->Vel + rsOuterNoise.m_amplitudeoffset;
|
volume = rsOuterNoise.m_amplitudefactor * MoverParameters->Vel + rsOuterNoise.m_amplitudeoffset;
|
||||||
frequency = rsOuterNoise.m_frequencyfactor * MoverParameters->Vel + rsOuterNoise.m_frequencyoffset;
|
frequency = rsOuterNoise.m_frequencyfactor * MoverParameters->Vel + rsOuterNoise.m_frequencyoffset;
|
||||||
@@ -4306,6 +4312,7 @@ void TDynamicObject::RenderSounds() {
|
|||||||
|
|
||||||
MoverParameters->EventFlag = false;
|
MoverParameters->EventFlag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// McZapkie-250202
|
// McZapkie-250202
|
||||||
@@ -5018,7 +5025,7 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName,
|
|||||||
{ sound_placement::external, static_cast<float>( dSDist ) } };
|
{ sound_placement::external, static_cast<float>( dSDist ) } };
|
||||||
axle.clatter.deserialize( parser, sound_type::single );
|
axle.clatter.deserialize( parser, sound_type::single );
|
||||||
axle.clatter.owner( this );
|
axle.clatter.owner( this );
|
||||||
axle.clatter.offset( { 0, 0, -axle.offset } );
|
axle.clatter.offset( { 0, 0, -axle.offset } ); // vehicle faces +Z in 'its' space, for axle locations negative value means ahead of centre
|
||||||
m_axlesounds.emplace_back( axle );
|
m_axlesounds.emplace_back( axle );
|
||||||
}
|
}
|
||||||
// arrange the axles in case they're listed out of order
|
// arrange the axles in case they're listed out of order
|
||||||
|
|||||||
@@ -5163,7 +5163,7 @@ TTrain::update_sounds( double const Deltatime ) {
|
|||||||
if( ( mvOccupied->BrakeHandle == FV4a )
|
if( ( mvOccupied->BrakeHandle == FV4a )
|
||||||
|| ( mvOccupied->BrakeHandle == FVel6 ) ) {
|
|| ( mvOccupied->BrakeHandle == FVel6 ) ) {
|
||||||
// upuszczanie z PG
|
// upuszczanie z PG
|
||||||
fPPress = interpolate<float>( fPPress, mvOccupied->Handle->GetSound( s_fv4a_b ), 0.05 );
|
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 :
|
||||||
@@ -5177,7 +5177,7 @@ TTrain::update_sounds( double const Deltatime ) {
|
|||||||
rsHiss.stop();
|
rsHiss.stop();
|
||||||
}
|
}
|
||||||
// napelnianie PG
|
// napelnianie PG
|
||||||
fNPress = interpolate<float>( fNPress, mvOccupied->Handle->GetSound( s_fv4a_u ), 0.25 );
|
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 :
|
||||||
@@ -5269,7 +5269,8 @@ TTrain::update_sounds( double const Deltatime ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// szum w czasie jazdy
|
// szum w czasie jazdy
|
||||||
if( DynamicObject->GetVelocity() > 0.5 ) {
|
if( ( false == FreeFlyModeFlag )
|
||||||
|
&& ( DynamicObject->GetVelocity() > 0.5 ) ) {
|
||||||
|
|
||||||
volume = rsRunningNoise.m_amplitudefactor * mvOccupied->Vel + rsRunningNoise.m_amplitudeoffset;
|
volume = rsRunningNoise.m_amplitudefactor * mvOccupied->Vel + rsRunningNoise.m_amplitudeoffset;
|
||||||
auto frequency { rsRunningNoise.m_frequencyfactor * mvOccupied->Vel + rsRunningNoise.m_frequencyoffset };
|
auto frequency { rsRunningNoise.m_frequencyfactor * mvOccupied->Vel + rsRunningNoise.m_frequencyoffset };
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ openal_source::sync_with( sound_properties const &State ) {
|
|||||||
auto const cutoffrange = (
|
auto const cutoffrange = (
|
||||||
is_multipart ?
|
is_multipart ?
|
||||||
EU07_SOUND_CUTOFFRANGE : // we keep multi-part sounds around longer, to minimize restarts as the sounds get out and back in range
|
EU07_SOUND_CUTOFFRANGE : // we keep multi-part sounds around longer, to minimize restarts as the sounds get out and back in range
|
||||||
sound_range * 7.5f );
|
sound_range * 5.0f );
|
||||||
if( glm::length2( sound_distance ) > std::min( ( cutoffrange * cutoffrange ), ( EU07_SOUND_CUTOFFRANGE * EU07_SOUND_CUTOFFRANGE ) ) ) {
|
if( glm::length2( sound_distance ) > std::min( ( cutoffrange * cutoffrange ), ( EU07_SOUND_CUTOFFRANGE * EU07_SOUND_CUTOFFRANGE ) ) ) {
|
||||||
stop();
|
stop();
|
||||||
is_synced = false; // flag sync failure for the controller
|
is_synced = false; // flag sync failure for the controller
|
||||||
@@ -124,6 +124,24 @@ openal_source::sync_with( sound_properties const &State ) {
|
|||||||
|
|
||||||
::alSourcef( id, AL_GAIN, properties.gain * properties.soundproofing * Global::AudioVolume );
|
::alSourcef( id, AL_GAIN, properties.gain * properties.soundproofing * Global::AudioVolume );
|
||||||
}
|
}
|
||||||
|
if( sound_range > 0 ) {
|
||||||
|
auto const rangesquared { sound_range * sound_range };
|
||||||
|
auto const distancesquared { glm::length2( sound_distance ) };
|
||||||
|
if( ( distancesquared > rangesquared )
|
||||||
|
|| ( false == is_in_range ) ) {
|
||||||
|
// if the emitter is outside of its nominal hearing range or was outside of it during last check
|
||||||
|
// adjust the volume to a suitable fraction of nominal value
|
||||||
|
auto const fadedistance { sound_range * 0.75 };
|
||||||
|
auto const rangefactor {
|
||||||
|
interpolate(
|
||||||
|
1.f, 0.f,
|
||||||
|
clamp<float>(
|
||||||
|
( distancesquared - rangesquared ) / ( fadedistance * fadedistance ),
|
||||||
|
0.f, 1.f ) ) };
|
||||||
|
::alSourcef( id, AL_GAIN, properties.gain * properties.soundproofing * rangefactor * Global::AudioVolume );
|
||||||
|
}
|
||||||
|
is_in_range = ( distancesquared <= rangesquared );
|
||||||
|
}
|
||||||
// pitch
|
// pitch
|
||||||
if( State.pitch != properties.pitch ) {
|
if( State.pitch != properties.pitch ) {
|
||||||
// pitch value has changed
|
// pitch value has changed
|
||||||
@@ -148,7 +166,7 @@ openal_source::range( float const Range ) {
|
|||||||
Range :
|
Range :
|
||||||
5 ) }; // range of -1 means sound of unlimited range, positioned at the listener
|
5 ) }; // range of -1 means sound of unlimited range, positioned at the listener
|
||||||
::alSourcef( id, AL_REFERENCE_DISTANCE, range * ( 1.f / 16.f ) );
|
::alSourcef( id, AL_REFERENCE_DISTANCE, range * ( 1.f / 16.f ) );
|
||||||
::alSourcef( id, AL_ROLLOFF_FACTOR, 1.5f );
|
::alSourcef( id, AL_ROLLOFF_FACTOR, 1.75f );
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets modifier applied to the pitch of sounds emitted by the source
|
// sets modifier applied to the pitch of sounds emitted by the source
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ struct openal_source {
|
|||||||
for( auto const buffer : buffers ) {
|
for( auto const buffer : buffers ) {
|
||||||
bufferids.emplace_back( audio::renderer.buffer( buffer ).id ); }
|
bufferids.emplace_back( audio::renderer.buffer( buffer ).id ); }
|
||||||
if( id != audio::null_resource ) {
|
if( id != audio::null_resource ) {
|
||||||
::alSourceQueueBuffers( id, bufferids.size(), bufferids.data() );
|
::alSourceQueueBuffers( id, static_cast<ALsizei>( bufferids.size() ), bufferids.data() );
|
||||||
::alSourceRewind( id ); }
|
::alSourceRewind( id ); }
|
||||||
return *this; }
|
return *this; }
|
||||||
// starts playback of queued buffers
|
// starts playback of queued buffers
|
||||||
@@ -91,6 +91,7 @@ private:
|
|||||||
float pitch_variation { 1.f }; // emitter-specific variation of the base pitch
|
float pitch_variation { 1.f }; // emitter-specific variation of the base pitch
|
||||||
float sound_range { 50.f }; // cached audible range of the emitted samples
|
float sound_range { 50.f }; // cached audible range of the emitted samples
|
||||||
glm::vec3 sound_distance; // cached distance between sound and the listener
|
glm::vec3 sound_distance; // cached distance between sound and the listener
|
||||||
|
bool is_in_range { false }; // helper, indicates the source was recently within audible range
|
||||||
bool is_multipart { false }; // multi-part sounds are kept alive at longer ranges
|
bool is_multipart { false }; // multi-part sounds are kept alive at longer ranges
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
34
sound.cpp
34
sound.cpp
@@ -41,14 +41,14 @@ sound_source::deserialize( cParser &Input, sound_type const Legacytype, int cons
|
|||||||
switch( Legacytype ) {
|
switch( Legacytype ) {
|
||||||
case sound_type::single: {
|
case sound_type::single: {
|
||||||
// single sample only
|
// single sample only
|
||||||
m_soundmain.buffer = audio::renderer.fetch_buffer( Input.getToken<std::string>( true, "\n\r\t ,;" ) );
|
m_soundmain.buffer = audio::renderer.fetch_buffer( deserialize_filename( Input ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case sound_type::multipart: {
|
case sound_type::multipart: {
|
||||||
// three samples: start, middle, stop
|
// three samples: start, middle, stop
|
||||||
m_soundbegin.buffer = audio::renderer.fetch_buffer( Input.getToken<std::string>( true, "\n\r\t ,;" ) );
|
m_soundbegin.buffer = audio::renderer.fetch_buffer( deserialize_filename( Input ) );
|
||||||
m_soundmain.buffer = audio::renderer.fetch_buffer( Input.getToken<std::string>( true, "\n\r\t ,;" ) );
|
m_soundmain.buffer = audio::renderer.fetch_buffer( deserialize_filename( Input ) );
|
||||||
m_soundend.buffer = audio::renderer.fetch_buffer( Input.getToken<std::string>( true, "\n\r\t ,;" ) );
|
m_soundend.buffer = audio::renderer.fetch_buffer( deserialize_filename( Input ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@@ -76,6 +76,32 @@ sound_source::deserialize( cParser &Input, sound_type const Legacytype, int cons
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extracts name of the sound file from provided data stream
|
||||||
|
std::string
|
||||||
|
sound_source::deserialize_filename( cParser &Input ) {
|
||||||
|
|
||||||
|
auto token { Input.getToken<std::string>( true, "\n\r\t ,;" ) };
|
||||||
|
if( token != "[" ) {
|
||||||
|
// simple case, single file
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
// if instead of filename we've encountered '[' this marks beginning of random sound set
|
||||||
|
// we retrieve all filenames from the set, then return a random one
|
||||||
|
std::vector<std::string> filenames;
|
||||||
|
while( ( ( token = Input.getToken<std::string>( true, "\n\r\t ,;" ) ) != "" )
|
||||||
|
&& ( token != "]" ) ) {
|
||||||
|
filenames.emplace_back( token );
|
||||||
|
}
|
||||||
|
if( false == filenames.empty() ) {
|
||||||
|
std::shuffle( std::begin( filenames ), std::end( filenames ), Global::random_engine );
|
||||||
|
return filenames.front();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// shouldn't ever get here but, eh
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// issues contextual play commands for the audio renderer
|
// issues contextual play commands for the audio renderer
|
||||||
void
|
void
|
||||||
sound_source::play( int const Flags ) {
|
sound_source::play( int const Flags ) {
|
||||||
|
|||||||
3
sound.h
3
sound.h
@@ -115,6 +115,9 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
|
// extracts name of the sound file from provided data stream
|
||||||
|
std::string
|
||||||
|
deserialize_filename( cParser &Input );
|
||||||
void
|
void
|
||||||
update_counter( audio::buffer_handle const Buffer, int const Value );
|
update_counter( audio::buffer_handle const Buffer, int const Value );
|
||||||
void
|
void
|
||||||
|
|||||||
Reference in New Issue
Block a user