mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 09:19:18 +02:00
openalsoft compatibility fixes, basic measures for exceeding audio source limit
This commit is contained in:
@@ -4162,7 +4162,7 @@ void TDynamicObject::RenderSounds() {
|
|||||||
}
|
}
|
||||||
if( std::abs( MoverParameters->nrot ) > 0.01 ) {
|
if( std::abs( MoverParameters->nrot ) > 0.01 ) {
|
||||||
// hamulce wzmagaja halas
|
// hamulce wzmagaja halas
|
||||||
volume *= 1 + MoverParameters->UnitBrakeForce / ( 1 + MoverParameters->MaxBrakeForce );
|
volume *= 1 + 0.25 * ( MoverParameters->UnitBrakeForce / ( 1 + MoverParameters->MaxBrakeForce ) );
|
||||||
}
|
}
|
||||||
// scale volume by track quality
|
// scale volume by track quality
|
||||||
volume *= ( 20.0 + MyTrack->iDamageFlag ) / 21;
|
volume *= ( 20.0 + MyTrack->iDamageFlag ) / 21;
|
||||||
|
|||||||
@@ -131,8 +131,11 @@ bool Global::FullPhysics { true }; // full calculations performed for each simul
|
|||||||
|
|
||||||
// parametry testowe (do testowania scenerii i obiektów)
|
// parametry testowe (do testowania scenerii i obiektów)
|
||||||
bool Global::bWireFrame = false;
|
bool Global::bWireFrame = false;
|
||||||
|
|
||||||
|
// sound renderer
|
||||||
bool Global::bSoundEnabled = true;
|
bool Global::bSoundEnabled = true;
|
||||||
float Global::AudioVolume = 1.0f;
|
float Global::AudioVolume = 1.0f;
|
||||||
|
std::string Global::AudioRenderer;
|
||||||
|
|
||||||
int Global::iWriteLogEnabled = 3; // maska bitowa: 1-zapis do pliku, 2-okienko, 4-nazwy torów
|
int Global::iWriteLogEnabled = 3; // maska bitowa: 1-zapis do pliku, 2-okienko, 4-nazwy torów
|
||||||
bool Global::MultipleLogs{ false };
|
bool Global::MultipleLogs{ false };
|
||||||
@@ -281,6 +284,10 @@ void Global::ConfigParse(cParser &Parser)
|
|||||||
Parser.getTokens();
|
Parser.getTokens();
|
||||||
Parser >> Global::bSoundEnabled;
|
Parser >> Global::bSoundEnabled;
|
||||||
}
|
}
|
||||||
|
else if( token == "sound.openal.renderer" ) {
|
||||||
|
// selected device for audio renderer
|
||||||
|
Global::AudioRenderer = Parser.getToken<std::string>( false ); // case-sensitive
|
||||||
|
}
|
||||||
// else if (str==AnsiString("renderalpha")) //McZapkie-1312302 - dwuprzebiegowe renderowanie
|
// else if (str==AnsiString("renderalpha")) //McZapkie-1312302 - dwuprzebiegowe renderowanie
|
||||||
// bRenderAlpha=(GetNextSymbol().LowerCase()==AnsiString("yes"));
|
// bRenderAlpha=(GetNextSymbol().LowerCase()==AnsiString("yes"));
|
||||||
else if (token == "physicslog")
|
else if (token == "physicslog")
|
||||||
|
|||||||
@@ -165,8 +165,6 @@ public:
|
|||||||
static bool VSync;
|
static bool VSync;
|
||||||
static bool bFreeFly;
|
static bool bFreeFly;
|
||||||
static bool bWireFrame;
|
static bool bWireFrame;
|
||||||
static bool bSoundEnabled;
|
|
||||||
static float AudioVolume;
|
|
||||||
// McZapkie-131202
|
// McZapkie-131202
|
||||||
static bool bAdjustScreenFreq;
|
static bool bAdjustScreenFreq;
|
||||||
static bool bEnableTraction;
|
static bool bEnableTraction;
|
||||||
@@ -215,6 +213,10 @@ public:
|
|||||||
static bool bSmoothTraction; // wygładzanie drutów
|
static bool bSmoothTraction; // wygładzanie drutów
|
||||||
static float SplineFidelity; // determines segment size during conversion of splines to geometry
|
static float SplineFidelity; // determines segment size during conversion of splines to geometry
|
||||||
static GLfloat FogColor[];
|
static GLfloat FogColor[];
|
||||||
|
// sound renderer variables
|
||||||
|
static bool bSoundEnabled;
|
||||||
|
static float AudioVolume;
|
||||||
|
static std::string AudioRenderer;
|
||||||
|
|
||||||
static bool FullPhysics; // full calculations performed for each simulation step
|
static bool FullPhysics; // full calculations performed for each simulation step
|
||||||
static int iSlowMotion;
|
static int iSlowMotion;
|
||||||
|
|||||||
@@ -24,14 +24,22 @@ float const EU07_SOUND_CUTOFFRANGE { 3000.f }; // 2750 m = max expected emitter
|
|||||||
void
|
void
|
||||||
openal_source::play() {
|
openal_source::play() {
|
||||||
|
|
||||||
|
if( id == audio::null_resource ) { return; } // no implementation-side source to match, no point
|
||||||
|
|
||||||
|
::alGetError(); // pop the error stack
|
||||||
::alSourcePlay( id );
|
::alSourcePlay( id );
|
||||||
is_playing = true;
|
is_playing = (
|
||||||
|
::alGetError() == AL_NO_ERROR ?
|
||||||
|
true :
|
||||||
|
false );
|
||||||
}
|
}
|
||||||
|
|
||||||
// stops the playback
|
// stops the playback
|
||||||
void
|
void
|
||||||
openal_source::stop() {
|
openal_source::stop() {
|
||||||
|
|
||||||
|
if( id == audio::null_resource ) { return; } // no implementation-side source to match, no point
|
||||||
|
|
||||||
loop( false );
|
loop( false );
|
||||||
// NOTE: workaround for potential edge cases where ::alSourceStop() doesn't set source which wasn't yet started to AL_STOPPED
|
// NOTE: workaround for potential edge cases where ::alSourceStop() doesn't set source which wasn't yet started to AL_STOPPED
|
||||||
int state;
|
int state;
|
||||||
@@ -49,19 +57,22 @@ 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
|
||||||
|
|
||||||
::alGetSourcei( id, AL_BUFFERS_PROCESSED, &buffer_index );
|
if( id != audio::null_resource ) {
|
||||||
// for multipart sounds trim away processed sources until only one remains, the last one may be set to looping by the controller
|
|
||||||
ALuint bufferid;
|
|
||||||
while( ( buffer_index > 0 )
|
|
||||||
&& ( buffers.size() > 1 ) ) {
|
|
||||||
::alSourceUnqueueBuffers( id, 1, &bufferid );
|
|
||||||
buffers.erase( std::begin( buffers ) );
|
|
||||||
--buffer_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
int state;
|
::alGetSourcei( id, AL_BUFFERS_PROCESSED, &buffer_index );
|
||||||
::alGetSourcei( id, AL_SOURCE_STATE, &state );
|
// for multipart sounds trim away processed sources until only one remains, the last one may be set to looping by the controller
|
||||||
is_playing = ( state == AL_PLAYING );
|
ALuint bufferid;
|
||||||
|
while( ( buffer_index > 0 )
|
||||||
|
&& ( buffers.size() > 1 ) ) {
|
||||||
|
::alSourceUnqueueBuffers( id, 1, &bufferid );
|
||||||
|
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
|
// request instructions from the controller
|
||||||
controller->update( *this );
|
controller->update( *this );
|
||||||
@@ -71,6 +82,11 @@ openal_source::update( double const Deltatime ) {
|
|||||||
void
|
void
|
||||||
openal_source::sync_with( sound_properties const &State ) {
|
openal_source::sync_with( sound_properties const &State ) {
|
||||||
|
|
||||||
|
if( id == audio::null_resource ) {
|
||||||
|
// no implementation-side source to match, return sync error so the controller can clean up on its end
|
||||||
|
is_synced = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
// velocity
|
// velocity
|
||||||
// not used yet
|
// not used yet
|
||||||
@@ -79,11 +95,14 @@ openal_source::sync_with( sound_properties const &State ) {
|
|||||||
// location
|
// location
|
||||||
properties.location = State.location;
|
properties.location = State.location;
|
||||||
auto sourceoffset { glm::vec3 { properties.location - glm::dvec3 { Global::pCameraPosition } } };
|
auto sourceoffset { glm::vec3 { properties.location - glm::dvec3 { Global::pCameraPosition } } };
|
||||||
if( glm::length2( sourceoffset ) > std::max( ( sound_range * sound_range ), ( EU07_SOUND_CUTOFFRANGE * EU07_SOUND_CUTOFFRANGE ) ) ) {
|
if( sound_range > 0 ) {
|
||||||
// range cutoff check
|
// range cutoff check
|
||||||
stop();
|
auto const cutoffrange { sound_range * 7.5f };
|
||||||
is_synced = false; // flag sync failure for the controller
|
if( glm::length2( sourceoffset ) > std::min( ( cutoffrange * cutoffrange ), ( EU07_SOUND_CUTOFFRANGE * EU07_SOUND_CUTOFFRANGE ) ) ) {
|
||||||
return;
|
stop();
|
||||||
|
is_synced = false; // flag sync failure for the controller
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if( sound_range >= 0 ) {
|
if( sound_range >= 0 ) {
|
||||||
::alSourcefv( id, AL_POSITION, glm::value_ptr( sourceoffset ) );
|
::alSourcefv( id, AL_POSITION, glm::value_ptr( sourceoffset ) );
|
||||||
@@ -116,14 +135,17 @@ openal_source::sync_with( sound_properties const &State ) {
|
|||||||
void
|
void
|
||||||
openal_source::range( float const Range ) {
|
openal_source::range( float const Range ) {
|
||||||
|
|
||||||
auto const range(
|
|
||||||
Range >= 0 ?
|
|
||||||
Range :
|
|
||||||
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_ROLLOFF_FACTOR, 1.5f );
|
|
||||||
// NOTE: we cache actual specified range, as we'll be giving 'unlimited' range special treatment
|
// NOTE: we cache actual specified range, as we'll be giving 'unlimited' range special treatment
|
||||||
sound_range = Range;
|
sound_range = Range;
|
||||||
|
|
||||||
|
if( id == audio::null_resource ) { return; } // no implementation-side source to match, no point
|
||||||
|
|
||||||
|
auto const range { (
|
||||||
|
Range >= 0 ?
|
||||||
|
Range :
|
||||||
|
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_ROLLOFF_FACTOR, 1.5f );
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets modifier applied to the pitch of sounds emitted by the source
|
// sets modifier applied to the pitch of sounds emitted by the source
|
||||||
@@ -139,6 +161,7 @@ openal_source::pitch( float const Pitch ) {
|
|||||||
void
|
void
|
||||||
openal_source::loop( bool const State ) {
|
openal_source::loop( bool const State ) {
|
||||||
|
|
||||||
|
if( id == audio::null_resource ) { return; } // no implementation-side source to match, no point
|
||||||
if( is_looping == State ) { return; }
|
if( is_looping == State ) { return; }
|
||||||
|
|
||||||
is_looping = State;
|
is_looping = State;
|
||||||
@@ -154,15 +177,19 @@ 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() {
|
||||||
// unqueue bound buffers:
|
|
||||||
// ensure no buffer is in use...
|
if( id != audio::null_resource ) {
|
||||||
stop();
|
// unqueue bound buffers:
|
||||||
// ...prepare space for returned ids of unqueued buffers (not that we need that info)...
|
// ensure no buffer is in use...
|
||||||
std::vector<ALuint> bufferids;
|
stop();
|
||||||
bufferids.resize( buffers.size() );
|
// ...prepare space for returned ids of unqueued buffers (not that we need that info)...
|
||||||
// ...release the buffers...
|
std::vector<ALuint> bufferids;
|
||||||
::alSourceUnqueueBuffers( id, bufferids.size(), bufferids.data() );
|
bufferids.resize( buffers.size() );
|
||||||
|
// ...release the buffers...
|
||||||
|
::alSourceUnqueueBuffers( id, bufferids.size(), bufferids.data() );
|
||||||
|
}
|
||||||
// ...and reset reset the properties, except for the id of the allocated source
|
// ...and reset reset the properties, except for the id of the allocated source
|
||||||
|
// NOTE: not strictly necessary since except for the id the source data typically get discarded in next step
|
||||||
auto const sourceid { id };
|
auto const sourceid { id };
|
||||||
*this = openal_source();
|
*this = openal_source();
|
||||||
id = sourceid;
|
id = sourceid;
|
||||||
@@ -231,7 +258,10 @@ openal_renderer::erase( sound_source const *Controller ) {
|
|||||||
if( source->controller == Controller ) {
|
if( source->controller == Controller ) {
|
||||||
// if the controller is the one specified, kill it
|
// if the controller is the one specified, kill it
|
||||||
source->clear();
|
source->clear();
|
||||||
m_sourcespares.push( *source );
|
if( source->id != audio::null_resource ) {
|
||||||
|
// keep around functional sources, but no point in doing it with the above-the-limit ones
|
||||||
|
m_sourcespares.push( source->id );
|
||||||
|
}
|
||||||
source = m_sources.erase( source );
|
source = m_sources.erase( source );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -268,7 +298,10 @@ openal_renderer::update( double const Deltatime ) {
|
|||||||
// if after the update the source isn't playing, put it away on the spare stack, it's done
|
// if after the update the source isn't playing, put it away on the spare stack, it's done
|
||||||
if( false == source->is_playing ) {
|
if( false == source->is_playing ) {
|
||||||
source->clear();
|
source->clear();
|
||||||
m_sourcespares.push( *source );
|
if( source->id != audio::null_resource ) {
|
||||||
|
// keep around functional sources, but no point in doing it with the above-the-limit ones
|
||||||
|
m_sourcespares.push( source->id );
|
||||||
|
}
|
||||||
source = m_sources.erase( source );
|
source = m_sources.erase( source );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -285,7 +318,7 @@ openal_renderer::fetch_source() {
|
|||||||
audio::openal_source soundsource;
|
audio::openal_source soundsource;
|
||||||
if( false == m_sourcespares.empty() ) {
|
if( false == m_sourcespares.empty() ) {
|
||||||
// reuse (a copy of) already allocated source
|
// reuse (a copy of) already allocated source
|
||||||
soundsource = m_sourcespares.top();
|
soundsource.id = m_sourcespares.top();
|
||||||
m_sourcespares.pop();
|
m_sourcespares.pop();
|
||||||
}
|
}
|
||||||
return soundsource;
|
return soundsource;
|
||||||
@@ -294,9 +327,8 @@ openal_renderer::fetch_source() {
|
|||||||
bool
|
bool
|
||||||
openal_renderer::init_caps() {
|
openal_renderer::init_caps() {
|
||||||
|
|
||||||
// select the "preferred device"
|
// NOTE: default value of audio renderer variable is empty string, meaning argument of NULL i.e. 'preferred' device
|
||||||
// TODO: support for opening config-specified device
|
m_device = ::alcOpenDevice( Global::AudioRenderer.c_str() );
|
||||||
m_device = ::alcOpenDevice( nullptr );
|
|
||||||
if( m_device == nullptr ) {
|
if( m_device == nullptr ) {
|
||||||
ErrorLog( "Failed to obtain audio device" );
|
ErrorLog( "Failed to obtain audio device" );
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -55,6 +55,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 ); }
|
||||||
::alSourceQueueBuffers( id, bufferids.size(), bufferids.data() );
|
::alSourceQueueBuffers( id, bufferids.size(), bufferids.data() );
|
||||||
|
::alSourceRewind( id );
|
||||||
return *this; }
|
return *this; }
|
||||||
// starts playback of queued buffers
|
// starts playback of queued buffers
|
||||||
void
|
void
|
||||||
@@ -128,7 +129,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
// types
|
// types
|
||||||
using source_list = std::list<audio::openal_source>;
|
using source_list = std::list<audio::openal_source>;
|
||||||
using source_sequence = std::stack<audio::openal_source>;
|
using source_sequence = std::stack<ALuint>;
|
||||||
// methods
|
// methods
|
||||||
bool
|
bool
|
||||||
init_caps();
|
init_caps();
|
||||||
|
|||||||
@@ -86,10 +86,7 @@ sound_source::play( int const Flags ) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if( m_range > 0 ) {
|
if( m_range > 0 ) {
|
||||||
auto const cutoffrange{ (
|
auto const cutoffrange{ m_range * 5 };
|
||||||
( m_soundbegin.buffer != null_handle ) && ( Flags & sound_flags::looping ) ?
|
|
||||||
m_range * 10 : // larger margin to let the startup sample finish playing at safe distance
|
|
||||||
m_range * 5 ) };
|
|
||||||
if( glm::length2( location() - glm::dvec3{ Global::pCameraPosition } ) > std::min( 2750.f * 2750.f, cutoffrange * cutoffrange ) ) {
|
if( glm::length2( location() - glm::dvec3{ Global::pCameraPosition } ) > std::min( 2750.f * 2750.f, cutoffrange * cutoffrange ) ) {
|
||||||
// drop sounds from beyond sensible and/or audible range
|
// drop sounds from beyond sensible and/or audible range
|
||||||
return;
|
return;
|
||||||
@@ -196,6 +193,10 @@ sound_source::update( audio::openal_source &Source ) {
|
|||||||
if( true == Source.is_synced ) {
|
if( true == Source.is_synced ) {
|
||||||
// all set, start playback
|
// all set, start playback
|
||||||
Source.play();
|
Source.play();
|
||||||
|
if( false == Source.is_playing ) {
|
||||||
|
// if the playback didn't start update the state counter
|
||||||
|
update_counter( buffer, -1 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// if the initial sync went wrong we skip the activation so the renderer can clean the emitter on its end
|
// if the initial sync went wrong we skip the activation so the renderer can clean the emitter on its end
|
||||||
|
|||||||
Reference in New Issue
Block a user