mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 05:49:19 +02:00
reformat: remove redundant qualifiers
This commit is contained in:
@@ -97,20 +97,20 @@ buffer_manager::~buffer_manager() {
|
||||
|
||||
for( auto &buffer : m_buffers ) {
|
||||
if( buffer.id != null_resource ) {
|
||||
::alDeleteBuffers( 1, &buffer.id );
|
||||
alDeleteBuffers( 1, &buffer.id );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// creates buffer object out of data stored in specified file. returns: handle to the buffer or null_handle if creation failed
|
||||
audio::buffer_handle
|
||||
buffer_handle
|
||||
buffer_manager::create( std::string const &Filename ) {
|
||||
|
||||
auto filename { ToLower( Filename ) };
|
||||
|
||||
erase_extension( filename );
|
||||
|
||||
audio::buffer_handle lookup { null_handle };
|
||||
buffer_handle lookup { null_handle };
|
||||
std::string filelookup;
|
||||
if( false == Global.asCurrentDynamicPath.empty() ) {
|
||||
// try dynamic-specific sounds first
|
||||
@@ -149,14 +149,14 @@ buffer_manager::create( std::string const &Filename ) {
|
||||
}
|
||||
|
||||
// provides direct access to a specified buffer
|
||||
audio::openal_buffer const &
|
||||
buffer_manager::buffer( audio::buffer_handle const Buffer ) const {
|
||||
openal_buffer const &
|
||||
buffer_manager::buffer( buffer_handle const Buffer ) const {
|
||||
|
||||
return m_buffers[ Buffer ];
|
||||
}
|
||||
|
||||
// places in the bank a buffer containing data stored in specified file. returns: handle to the buffer
|
||||
audio::buffer_handle
|
||||
buffer_handle
|
||||
buffer_manager::emplace( std::string Filename ) {
|
||||
|
||||
buffer_handle const handle { m_buffers.size() };
|
||||
@@ -171,7 +171,7 @@ buffer_manager::emplace( std::string Filename ) {
|
||||
return handle;
|
||||
}
|
||||
|
||||
audio::buffer_handle
|
||||
buffer_handle
|
||||
buffer_manager::find_buffer( std::string const &Buffername ) const {
|
||||
|
||||
auto const lookup = m_buffermappings.find( Buffername );
|
||||
|
||||
@@ -54,8 +54,8 @@ public:
|
||||
buffer_handle
|
||||
create( std::string const &Filename );
|
||||
// provides direct access to a specified buffer
|
||||
audio::openal_buffer const &
|
||||
buffer( audio::buffer_handle const Buffer ) const;
|
||||
openal_buffer const &
|
||||
buffer( buffer_handle const Buffer ) const;
|
||||
|
||||
private:
|
||||
// types
|
||||
|
||||
@@ -39,12 +39,12 @@ limit_velocity( glm::vec3 const &Velocity ) {
|
||||
void
|
||||
openal_source::play() {
|
||||
|
||||
if( id == audio::null_resource ) { return; } // no implementation-side source to match, no point
|
||||
if( id == null_resource ) { return; } // no implementation-side source to match, no point
|
||||
|
||||
::alSourcePlay( id );
|
||||
alSourcePlay( id );
|
||||
|
||||
ALint state;
|
||||
::alGetSourcei( id, AL_SOURCE_STATE, &state );
|
||||
alGetSourcei( id, AL_SOURCE_STATE, &state );
|
||||
is_playing = state == AL_PLAYING;
|
||||
}
|
||||
|
||||
@@ -52,16 +52,16 @@ openal_source::play() {
|
||||
void
|
||||
openal_source::stop() {
|
||||
|
||||
if( id == audio::null_resource ) { return; } // no implementation-side source to match, no point
|
||||
if( id == null_resource ) { return; } // no implementation-side source to match, no point
|
||||
|
||||
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 );
|
||||
alGetSourcei( id, AL_SOURCE_STATE, &state );
|
||||
if( state == AL_INITIAL ) {
|
||||
play();
|
||||
}
|
||||
::alSourceStop( id );
|
||||
alSourceStop( id );
|
||||
is_playing = false;
|
||||
}
|
||||
|
||||
@@ -80,29 +80,29 @@ openal_source::update( double const Deltatime, glm::vec3 const &Listenervelocity
|
||||
stop();
|
||||
}
|
||||
*/
|
||||
if( id != audio::null_resource ) {
|
||||
if( id != null_resource ) {
|
||||
|
||||
sound_change = false;
|
||||
::alGetSourcei( id, AL_BUFFERS_PROCESSED, &sound_index );
|
||||
alGetSourcei( id, AL_BUFFERS_PROCESSED, &sound_index );
|
||||
// for multipart sounds trim away processed buffers until only one remains, the last one may be set to looping by the controller
|
||||
// TBD, TODO: instead of change flag move processed buffer ids to separate queue, for accurate tracking of longer buffer sequences
|
||||
ALuint discard;
|
||||
while( sound_index > 0
|
||||
&& sounds.size() > 1 ) {
|
||||
::alSourceUnqueueBuffers( id, 1, &discard );
|
||||
alSourceUnqueueBuffers( id, 1, &discard );
|
||||
sounds.erase( std::begin( sounds ) );
|
||||
--sound_index;
|
||||
sound_change = true;
|
||||
// potentially adjust starting point of the last buffer (to reduce chance of reverb effect with multiple, looping copies playing)
|
||||
if( controller->start() > 0.f && sounds.size() == 1 ) {
|
||||
ALint bufferid;
|
||||
::alGetSourcei(
|
||||
alGetSourcei(
|
||||
id,
|
||||
AL_BUFFER,
|
||||
&bufferid );
|
||||
ALint buffersize;
|
||||
::alGetBufferi( bufferid, AL_SIZE, &buffersize );
|
||||
::alSourcei(
|
||||
alGetBufferi( bufferid, AL_SIZE, &buffersize );
|
||||
alSourcei(
|
||||
id,
|
||||
AL_SAMPLE_OFFSET,
|
||||
static_cast<ALint>( controller->start() * ( buffersize / sizeof( std::int16_t ) ) ) );
|
||||
@@ -110,7 +110,7 @@ openal_source::update( double const Deltatime, glm::vec3 const &Listenervelocity
|
||||
}
|
||||
|
||||
int state;
|
||||
::alGetSourcei( id, AL_SOURCE_STATE, &state );
|
||||
alGetSourcei( id, AL_SOURCE_STATE, &state );
|
||||
is_playing = state == AL_PLAYING;
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ openal_source::update( double const Deltatime, glm::vec3 const &Listenervelocity
|
||||
void
|
||||
openal_source::sync_with( sound_properties const &State ) {
|
||||
|
||||
if( id == audio::null_resource ) {
|
||||
if( id == null_resource ) {
|
||||
// no implementation-side source to match, return sync error so the controller can clean up on its end
|
||||
sync = sync_state::bad_resource;
|
||||
return;
|
||||
@@ -135,7 +135,7 @@ openal_source::sync_with( sound_properties const &State ) {
|
||||
sound_velocity = limit_velocity( ( State.location - properties.location ) / update_deltatime );
|
||||
}
|
||||
// NOTE: velocity at this point can be either listener velocity for global sounds, actual sound velocity, or 0 if sound position is yet unknown
|
||||
::alSourcefv( id, AL_VELOCITY, glm::value_ptr( sound_velocity ) );
|
||||
alSourcefv( id, AL_VELOCITY, glm::value_ptr( sound_velocity ) );
|
||||
|
||||
// location
|
||||
sound_distance = State.location - renderer.cached_camerapos;
|
||||
@@ -151,11 +151,11 @@ openal_source::sync_with( sound_properties const &State ) {
|
||||
}
|
||||
}
|
||||
if( sound_range >= 0 ) {
|
||||
::alSourcefv( id, AL_POSITION, glm::value_ptr( sound_distance ) );
|
||||
alSourcefv( id, AL_POSITION, glm::value_ptr( sound_distance ) );
|
||||
}
|
||||
else {
|
||||
// sounds with 'unlimited' or negative range are positioned on top of the listener
|
||||
::alSourcefv( id, AL_POSITION, glm::value_ptr( glm::vec3() ) );
|
||||
alSourcefv( id, AL_POSITION, glm::value_ptr( glm::vec3() ) );
|
||||
}
|
||||
// gain
|
||||
auto const gain {
|
||||
@@ -167,14 +167,14 @@ openal_source::sync_with( sound_properties const &State ) {
|
||||
1.f ) };
|
||||
if( State.gain != properties.gain
|
||||
|| State.soundproofing_stamp != properties.soundproofing_stamp
|
||||
|| audio::event_volume_change ) {
|
||||
|| event_volume_change ) {
|
||||
// gain value has changed
|
||||
::alSourcef( id, AL_GAIN, gain );
|
||||
alSourcef( id, AL_GAIN, gain );
|
||||
auto const range { (
|
||||
sound_range >= 0 ?
|
||||
sound_range :
|
||||
5 ) }; // range of -1 means sound of unlimited range, positioned at the listener
|
||||
::alSourcef( id, AL_REFERENCE_DISTANCE, range * ( 1.f / 16.f ) * State.soundproofing );
|
||||
alSourcef( id, AL_REFERENCE_DISTANCE, range * ( 1.f / 16.f ) * State.soundproofing );
|
||||
}
|
||||
if( sound_range != -1 ) {
|
||||
auto const rangesquared { sound_range * sound_range };
|
||||
@@ -189,14 +189,14 @@ openal_source::sync_with( sound_properties const &State ) {
|
||||
1.f, 0.f, std::clamp(
|
||||
( distancesquared - rangesquared ) / ( fadedistance * fadedistance ),
|
||||
0.f, 1.f ) ) };
|
||||
::alSourcef( id, AL_GAIN, gain * rangefactor );
|
||||
alSourcef( id, AL_GAIN, gain * rangefactor );
|
||||
}
|
||||
is_in_range = distancesquared <= rangesquared;
|
||||
}
|
||||
// pitch
|
||||
if( State.pitch != properties.pitch ) {
|
||||
// pitch value has changed
|
||||
::alSourcef( id, AL_PITCH, std::clamp( State.pitch * pitch_variation, 0.1f, 10.f ) );
|
||||
alSourcef( id, AL_PITCH, std::clamp( State.pitch * pitch_variation, 0.1f, 10.f ) );
|
||||
}
|
||||
// all synced up
|
||||
properties = State;
|
||||
@@ -210,14 +210,14 @@ openal_source::range( float const Range ) {
|
||||
// NOTE: we cache actual specified range, as we'll be giving 'unlimited' range special treatment
|
||||
sound_range = Range;
|
||||
|
||||
if( id == audio::null_resource ) { return; } // no implementation-side source to match, no point
|
||||
if( id == 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.75f );
|
||||
alSourcef( id, AL_REFERENCE_DISTANCE, range * ( 1.f / 16.f ) );
|
||||
alSourcef( id, AL_ROLLOFF_FACTOR, 1.75f );
|
||||
}
|
||||
|
||||
// sets modifier applied to the pitch of sounds emitted by the source
|
||||
@@ -233,11 +233,11 @@ openal_source::pitch( float const Pitch ) {
|
||||
void
|
||||
openal_source::loop( bool const State ) {
|
||||
|
||||
if( id == audio::null_resource ) { return; } // no implementation-side source to match, no point
|
||||
if( id == null_resource ) { return; } // no implementation-side source to match, no point
|
||||
if( is_looping == State ) { return; }
|
||||
|
||||
is_looping = State;
|
||||
::alSourcei(
|
||||
alSourcei(
|
||||
id,
|
||||
AL_LOOPING,
|
||||
State ? AL_TRUE : AL_FALSE);
|
||||
@@ -248,7 +248,7 @@ openal_source::loop( bool const State ) {
|
||||
void
|
||||
openal_source::clear() {
|
||||
|
||||
if( id != audio::null_resource ) {
|
||||
if( id != null_resource ) {
|
||||
// unqueue bound buffers:
|
||||
// ensure no buffer is in use...
|
||||
stop();
|
||||
@@ -256,7 +256,7 @@ openal_source::clear() {
|
||||
std::vector<ALuint> bufferids;
|
||||
bufferids.resize( sounds.size() );
|
||||
// ...release the buffers...
|
||||
::alSourceUnqueueBuffers( id, bufferids.size(), bufferids.data() );
|
||||
alSourceUnqueueBuffers( id, bufferids.size(), bufferids.data() );
|
||||
}
|
||||
// ...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
|
||||
@@ -269,21 +269,21 @@ openal_source::clear() {
|
||||
|
||||
openal_renderer::~openal_renderer() {
|
||||
|
||||
::alcMakeContextCurrent( nullptr );
|
||||
alcMakeContextCurrent( nullptr );
|
||||
|
||||
if( m_context != nullptr ) { ::alcDestroyContext( m_context ); }
|
||||
if( m_device != nullptr ) { ::alcCloseDevice( m_device ); }
|
||||
if( m_context != nullptr ) { alcDestroyContext( m_context ); }
|
||||
if( m_device != nullptr ) { alcCloseDevice( m_device ); }
|
||||
}
|
||||
|
||||
audio::buffer_handle
|
||||
buffer_handle
|
||||
openal_renderer::fetch_buffer( std::string const &Filename ) {
|
||||
|
||||
return m_buffers.create( Filename );
|
||||
}
|
||||
|
||||
// provides direct access to a specified buffer
|
||||
audio::openal_buffer const &
|
||||
openal_renderer::buffer( audio::buffer_handle const Buffer ) const {
|
||||
openal_buffer const &
|
||||
openal_renderer::buffer( buffer_handle const Buffer ) const {
|
||||
|
||||
return m_buffers.buffer( Buffer );
|
||||
}
|
||||
@@ -300,8 +300,8 @@ openal_renderer::init() {
|
||||
// basic initialization failed
|
||||
return false;
|
||||
}
|
||||
::alDistanceModel( AL_INVERSE_DISTANCE_CLAMPED );
|
||||
::alDopplerFactor( 0.25f );
|
||||
alDistanceModel( AL_INVERSE_DISTANCE_CLAMPED );
|
||||
alDopplerFactor( 0.25f );
|
||||
// all done
|
||||
m_ready = true;
|
||||
return true;
|
||||
@@ -316,7 +316,7 @@ openal_renderer::erase( sound_source const *Controller ) {
|
||||
if( source->controller == Controller ) {
|
||||
// if the controller is the one specified, kill it
|
||||
source->clear();
|
||||
if( source->id != audio::null_resource ) {
|
||||
if( source->id != null_resource ) {
|
||||
// keep around functional sources, but no point in doing it with the above-the-limit ones
|
||||
m_sourcespares.push( source->id );
|
||||
}
|
||||
@@ -349,7 +349,7 @@ openal_renderer::update( double const Deltatime ) {
|
||||
errname = "AL_OUT_OF_MEMORY";
|
||||
else
|
||||
errname = "unknown";
|
||||
|
||||
|
||||
ErrorLog("sound: al error: " + errname);
|
||||
}
|
||||
|
||||
@@ -365,7 +365,7 @@ openal_renderer::update( double const Deltatime ) {
|
||||
|
||||
// update listener
|
||||
// gain
|
||||
::alListenerf( AL_GAIN, Global.AudioVolume );
|
||||
alListenerf( AL_GAIN, Global.AudioVolume );
|
||||
// orientation
|
||||
glm::dmat4 cameramatrix;
|
||||
Global.pCamera.SetMatrix( cameramatrix );
|
||||
@@ -375,7 +375,7 @@ openal_renderer::update( double const Deltatime ) {
|
||||
glm::vec3 const orientation[] = {
|
||||
glm::vec3{ 0, 0,-1 } * rotationmatrix ,
|
||||
glm::vec3{ 0, 1, 0 } * rotationmatrix };
|
||||
::alListenerfv( AL_ORIENTATION, reinterpret_cast<ALfloat const *>( orientation ) );
|
||||
alListenerfv( AL_ORIENTATION, reinterpret_cast<ALfloat const *>( orientation ) );
|
||||
// velocity
|
||||
if( Deltatime > 0 ) {
|
||||
auto cameramove { cameraposition - cached_camerapos };
|
||||
@@ -402,7 +402,7 @@ openal_renderer::update( double const Deltatime ) {
|
||||
}
|
||||
m_listenervelocity = limit_velocity( cameramove / Deltatime );
|
||||
|
||||
::alListenerfv( AL_VELOCITY, reinterpret_cast<ALfloat const *>( glm::value_ptr( m_listenervelocity ) ) );
|
||||
alListenerfv( AL_VELOCITY, reinterpret_cast<ALfloat const *>( glm::value_ptr( m_listenervelocity ) ) );
|
||||
}
|
||||
|
||||
// update active emitters
|
||||
@@ -413,7 +413,7 @@ 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( false == source->is_playing ) {
|
||||
source->clear();
|
||||
if( source->id != audio::null_resource ) {
|
||||
if( source->id != null_resource ) {
|
||||
// keep around functional sources, but no point in doing it with the above-the-limit ones
|
||||
m_sourcespares.push( source->id );
|
||||
}
|
||||
@@ -426,7 +426,7 @@ openal_renderer::update( double const Deltatime ) {
|
||||
}
|
||||
|
||||
// reset potentially used volume change flag
|
||||
audio::event_volume_change = false;
|
||||
event_volume_change = false;
|
||||
|
||||
if (alProcessUpdatesSOFT)
|
||||
{
|
||||
@@ -436,20 +436,20 @@ openal_renderer::update( double const Deltatime ) {
|
||||
}
|
||||
|
||||
// returns an instance of implementation-side part of the sound emitter
|
||||
audio::openal_source
|
||||
openal_source
|
||||
openal_renderer::fetch_source() {
|
||||
|
||||
audio::openal_source newsource;
|
||||
openal_source newsource;
|
||||
if( false == m_sourcespares.empty() ) {
|
||||
// reuse (a copy of) already allocated source
|
||||
newsource.id = m_sourcespares.top();
|
||||
m_sourcespares.pop();
|
||||
}
|
||||
if( newsource.id == audio::null_resource ) {
|
||||
if( newsource.id == null_resource ) {
|
||||
// if there's no source to reuse, try to generate a new one
|
||||
::alGenSources( 1, &newsource.id );
|
||||
alGenSources( 1, &newsource.id );
|
||||
}
|
||||
if( newsource.id == audio::null_resource ) {
|
||||
if( newsource.id == null_resource ) {
|
||||
alGetError();
|
||||
// if we still don't have a working source, see if we can sacrifice an already active one
|
||||
// under presumption it's more important to play new sounds than keep the old ones going
|
||||
@@ -460,7 +460,7 @@ openal_renderer::fetch_source() {
|
||||
|
||||
for( auto source { std::begin( m_sources ) }; source != std::cend( m_sources ); ++source ) {
|
||||
|
||||
if( source->id == audio::null_resource
|
||||
if( source->id == null_resource
|
||||
|| true == source->is_multipart
|
||||
|| false == source->is_playing ) {
|
||||
|
||||
@@ -488,12 +488,12 @@ openal_renderer::fetch_source() {
|
||||
}
|
||||
}
|
||||
|
||||
if( newsource.id == audio::null_resource ) {
|
||||
if( newsource.id == null_resource ) {
|
||||
// for sources with functional emitter reset emitter parameters from potential last use
|
||||
::alSourcef( newsource.id, AL_PITCH, 1.f );
|
||||
::alSourcef( newsource.id, AL_GAIN, 1.f );
|
||||
::alSourcefv( newsource.id, AL_POSITION, glm::value_ptr( glm::vec3{ 0.f } ) );
|
||||
::alSourcefv( newsource.id, AL_VELOCITY, glm::value_ptr( glm::vec3{ 0.f } ) );
|
||||
alSourcef( newsource.id, AL_PITCH, 1.f );
|
||||
alSourcef( newsource.id, AL_GAIN, 1.f );
|
||||
alSourcefv( newsource.id, AL_POSITION, glm::value_ptr( glm::vec3{ 0.f } ) );
|
||||
alSourcefv( newsource.id, AL_VELOCITY, glm::value_ptr( glm::vec3{ 0.f } ) );
|
||||
}
|
||||
|
||||
return newsource;
|
||||
@@ -502,10 +502,10 @@ openal_renderer::fetch_source() {
|
||||
bool
|
||||
openal_renderer::init_caps() {
|
||||
|
||||
if( ::alcIsExtensionPresent( nullptr, "ALC_ENUMERATION_EXT" ) == AL_TRUE ) {
|
||||
if( alcIsExtensionPresent( nullptr, "ALC_ENUMERATION_EXT" ) == AL_TRUE ) {
|
||||
// enumeration supported
|
||||
WriteLog( "available audio devices:" );
|
||||
auto const *devices { ::alcGetString( nullptr, ALC_DEVICE_SPECIFIER ) };
|
||||
auto const *devices { alcGetString( nullptr, ALC_DEVICE_SPECIFIER ) };
|
||||
auto const
|
||||
*device { devices },
|
||||
*next { devices + 1 };
|
||||
@@ -518,18 +518,18 @@ openal_renderer::init_caps() {
|
||||
}
|
||||
|
||||
// NOTE: default value of audio renderer variable is empty string, meaning argument of NULL i.e. 'preferred' device
|
||||
m_device = ::alcOpenDevice( Global.AudioRenderer.c_str() );
|
||||
m_device = alcOpenDevice( Global.AudioRenderer.c_str() );
|
||||
if( m_device == nullptr ) {
|
||||
ErrorLog( "Failed to obtain audio device" );
|
||||
return false;
|
||||
}
|
||||
|
||||
ALCint versionmajor, versionminor;
|
||||
::alcGetIntegerv( m_device, ALC_MAJOR_VERSION, 1, &versionmajor );
|
||||
::alcGetIntegerv( m_device, ALC_MINOR_VERSION, 1, &versionminor );
|
||||
alcGetIntegerv( m_device, ALC_MAJOR_VERSION, 1, &versionmajor );
|
||||
alcGetIntegerv( m_device, ALC_MINOR_VERSION, 1, &versionminor );
|
||||
auto const oalversion { std::to_string( versionmajor ) + "." + std::to_string( versionminor ) };
|
||||
|
||||
const std::string al_renderer((char *)::alcGetString( m_device, ALC_DEVICE_SPECIFIER ));
|
||||
const std::string al_renderer((char *)alcGetString( m_device, ALC_DEVICE_SPECIFIER ));
|
||||
crashreport_add_info("openal_renderer", al_renderer);
|
||||
crashreport_add_info("openal_version", oalversion);
|
||||
|
||||
@@ -537,11 +537,11 @@ openal_renderer::init_caps() {
|
||||
"Audio Renderer: " + al_renderer
|
||||
+ " OpenAL Version: " + oalversion );
|
||||
|
||||
WriteLog( "Supported extensions: " + std::string{ (char *)::alcGetString( m_device, ALC_EXTENSIONS ) } );
|
||||
WriteLog( "Supported extensions: " + std::string{ (char *)alcGetString( m_device, ALC_EXTENSIONS ) } );
|
||||
|
||||
const ALCint attr[3] = { ALC_MONO_SOURCES, Global.audio_max_sources, 0 }; // request more sounds
|
||||
|
||||
m_context = ::alcCreateContext( m_device, attr );
|
||||
m_context = alcCreateContext( m_device, attr );
|
||||
if( m_context == nullptr ) {
|
||||
ErrorLog( "Failed to create audio context" );
|
||||
return false;
|
||||
|
||||
@@ -52,10 +52,10 @@ struct openal_source {
|
||||
friend class openal_renderer;
|
||||
|
||||
// types
|
||||
using buffer_sequence = std::vector<audio::buffer_handle>;
|
||||
using buffer_sequence = std::vector<buffer_handle>;
|
||||
|
||||
// members
|
||||
ALuint id { audio::null_resource }; // associated AL resource
|
||||
ALuint id { null_resource }; // associated AL resource
|
||||
sound_source *controller { nullptr }; // source controller
|
||||
uint32_sequence sounds; //
|
||||
// buffer_sequence buffers; // sequence of samples the source will emit
|
||||
@@ -122,11 +122,11 @@ public:
|
||||
// methods
|
||||
// buffer methods
|
||||
// returns handle to a buffer containing audio data from specified file
|
||||
audio::buffer_handle
|
||||
buffer_handle
|
||||
fetch_buffer( std::string const &Filename );
|
||||
// provides direct access to a specified buffer
|
||||
audio::openal_buffer const &
|
||||
buffer( audio::buffer_handle const Buffer ) const;
|
||||
openal_buffer const &
|
||||
buffer( buffer_handle const Buffer ) const;
|
||||
// core methods
|
||||
// initializes the service
|
||||
bool
|
||||
@@ -147,13 +147,13 @@ public:
|
||||
|
||||
private:
|
||||
// types
|
||||
using source_list = std::list<audio::openal_source>;
|
||||
using source_list = std::list<openal_source>;
|
||||
using source_sequence = std::stack<ALuint>;
|
||||
// methods
|
||||
bool
|
||||
init_caps();
|
||||
// returns an instance of implementation-side part of the sound emitter
|
||||
audio::openal_source
|
||||
openal_source
|
||||
fetch_source();
|
||||
// members
|
||||
ALCdevice * m_device { nullptr };
|
||||
|
||||
@@ -11,27 +11,27 @@ openal_source::bind( sound_source *Controller, uint32_sequence Sounds, Iterator_
|
||||
std::vector<ALuint> buffers;
|
||||
std::for_each(
|
||||
First, Last,
|
||||
[&]( audio::buffer_handle const &bufferhandle ) {
|
||||
auto const &buffer { audio::renderer.buffer( bufferhandle ) };
|
||||
[&]( buffer_handle const &bufferhandle ) {
|
||||
auto const &buffer { renderer.buffer( bufferhandle ) };
|
||||
if (buffer.id != null_resource) buffers.emplace_back( buffer.id ); } );
|
||||
|
||||
is_multipart = buffers.size() > 1;
|
||||
|
||||
if( id != audio::null_resource && !buffers.empty()) {
|
||||
::alSourceQueueBuffers( id, static_cast<ALsizei>( buffers.size() ), buffers.data() );
|
||||
::alSourceRewind( id );
|
||||
if( id != null_resource && !buffers.empty()) {
|
||||
alSourceQueueBuffers( id, static_cast<ALsizei>( buffers.size() ), buffers.data() );
|
||||
alSourceRewind( id );
|
||||
// sound controller can potentially request playback to start from certain buffer point
|
||||
// for multipart sounds the offset is applied only to last piece during playback
|
||||
// for single sound we also make sure not to apply the offset to optional bookends
|
||||
if( controller->start() == 0.f || is_multipart || controller->is_bookend( buffers.front() ) ) {
|
||||
// regular case with no offset, reset bound source just in case
|
||||
::alSourcei( id, AL_SAMPLE_OFFSET, 0 );
|
||||
alSourcei( id, AL_SAMPLE_OFFSET, 0 );
|
||||
}
|
||||
else {
|
||||
// move playback start to specified point in 0-1 range
|
||||
ALint buffersize;
|
||||
::alGetBufferi( buffers.front(), AL_SIZE, &buffersize );
|
||||
::alSourcei(
|
||||
alGetBufferi( buffers.front(), AL_SIZE, &buffersize );
|
||||
alSourcei(
|
||||
id,
|
||||
AL_SAMPLE_OFFSET,
|
||||
static_cast<ALint>( controller->start() * ( buffersize / sizeof( std::int16_t ) ) ) );
|
||||
|
||||
106
audio/sound.cpp
106
audio/sound.cpp
@@ -122,14 +122,14 @@ sound_source::deserialize( cParser &Input, sound_type const Legacytype, int cons
|
||||
Input >> m_range;
|
||||
}
|
||||
}
|
||||
if( Legacyparameters & sound_parameters::amplitude ) {
|
||||
if( Legacyparameters & amplitude ) {
|
||||
if( Input.getTokens( 2, false ) ) {
|
||||
Input
|
||||
>> m_amplitudefactor
|
||||
>> m_amplitudeoffset;
|
||||
}
|
||||
}
|
||||
if( Legacyparameters & sound_parameters::frequency ) {
|
||||
if( Legacyparameters & frequency ) {
|
||||
if( Input.getTokens( 2, false ) ) {
|
||||
Input
|
||||
>> m_frequencyfactor
|
||||
@@ -161,16 +161,16 @@ sound_source::deserialize_mapping( cParser &Input ) {
|
||||
|
||||
// if not block end then the key is followed by assigned value or sub-block
|
||||
if( key == "soundmain:" ) {
|
||||
sound( sound_id::main ).buffer = audio::renderer.fetch_buffer( deserialize_random_set( Input, "\n\r\t ,;" ) );
|
||||
sound( main ).buffer = audio::renderer.fetch_buffer( deserialize_random_set( Input, "\n\r\t ,;" ) );
|
||||
}
|
||||
else if( key == "soundset:" ) {
|
||||
deserialize_soundset( Input );
|
||||
}
|
||||
else if( key == "soundbegin:" ) {
|
||||
sound( sound_id::begin ).buffer = audio::renderer.fetch_buffer( deserialize_random_set( Input, "\n\r\t ,;" ) );
|
||||
sound( begin ).buffer = audio::renderer.fetch_buffer( deserialize_random_set( Input, "\n\r\t ,;" ) );
|
||||
}
|
||||
else if( key == "soundend:" ) {
|
||||
sound( sound_id::end ).buffer = audio::renderer.fetch_buffer( deserialize_random_set( Input, "\n\r\t ,;" ) );
|
||||
sound( end ).buffer = audio::renderer.fetch_buffer( deserialize_random_set( Input, "\n\r\t ,;" ) );
|
||||
}
|
||||
else if( key == "soundproofing:" ) {
|
||||
// custom soundproofing in format [ p1, p2, p3, p4, p5, p6 ]
|
||||
@@ -286,9 +286,9 @@ sound_source::deserialize_soundset( cParser &Input ) {
|
||||
auto const soundset { deserialize_random_set( Input, "\n\r\t ,;" ) };
|
||||
// split retrieved set
|
||||
cParser setparser( soundset );
|
||||
sound( sound_id::begin ).buffer = audio::renderer.fetch_buffer( setparser.getToken<std::string>( true, "|" ) );
|
||||
sound( sound_id::main ).buffer = audio::renderer.fetch_buffer( setparser.getToken<std::string>( true, "|" ) );
|
||||
sound( sound_id::end ).buffer = audio::renderer.fetch_buffer( setparser.getToken<std::string>( true, "|" ) );
|
||||
sound( begin ).buffer = audio::renderer.fetch_buffer( setparser.getToken<std::string>( true, "|" ) );
|
||||
sound( main ).buffer = audio::renderer.fetch_buffer( setparser.getToken<std::string>( true, "|" ) );
|
||||
sound( end ).buffer = audio::renderer.fetch_buffer( setparser.getToken<std::string>( true, "|" ) );
|
||||
}
|
||||
|
||||
// sends content of the class in legacy (text) format to provided stream
|
||||
@@ -296,7 +296,7 @@ sound_source::deserialize_soundset( cParser &Input ) {
|
||||
void
|
||||
sound_source::export_as_text( std::ostream &Output ) const {
|
||||
|
||||
if( sound( sound_id::main ).buffer == null_handle ) { return; }
|
||||
if( sound( main ).buffer == null_handle ) { return; }
|
||||
|
||||
// generic node header
|
||||
Output
|
||||
@@ -315,7 +315,7 @@ sound_source::export_as_text( std::ostream &Output ) const {
|
||||
<< m_offset.y << ' '
|
||||
<< m_offset.z << ' ';
|
||||
// sound data
|
||||
auto soundfile { audio::renderer.buffer( sound( sound_id::main ).buffer ).name };
|
||||
auto soundfile { audio::renderer.buffer( sound( main ).buffer ).name };
|
||||
if( soundfile.find( paths::sounds ) == 0 ) {
|
||||
// don't include 'sounds/' in the path
|
||||
soundfile.erase( 0, std::string{ paths::sounds }.size() );
|
||||
@@ -383,7 +383,7 @@ sound_source::play( int const Flags ) {
|
||||
// TBD, TODO: user-configurable
|
||||
m_properties.category = m_owner ? sound_category::vehicle : m_range < 0 ? sound_category::ambient : sound_category::local;
|
||||
|
||||
if( sound( sound_id::main ).buffer != null_handle ) {
|
||||
if( sound( main ).buffer != null_handle ) {
|
||||
// basic variant: single main sound, with optional bookends
|
||||
play_basic();
|
||||
}
|
||||
@@ -399,20 +399,20 @@ sound_source::play_basic() {
|
||||
if( false == is_playing() ) {
|
||||
// dispatch appropriate sound
|
||||
if( true == m_playbeginning
|
||||
&& sound(sound_id::begin).buffer != null_handle) {
|
||||
std::vector<sound_id> sounds { sound_id::begin, sound_id::main };
|
||||
&& sound(begin).buffer != null_handle) {
|
||||
std::vector<sound_id> sounds { begin, main };
|
||||
insert( std::begin( sounds ), std::end( sounds ) );
|
||||
m_playbeginning = false;
|
||||
}
|
||||
else {
|
||||
insert( sound_id::main );
|
||||
insert( main );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// for single part non-looping samples we allow spawning multiple instances, if not prevented by set flags
|
||||
if( (m_flags & (sound_flags::exclusive | sound_flags::looping)) == 0
|
||||
&& sound(sound_id::begin).buffer == null_handle) {
|
||||
insert( sound_id::main );
|
||||
if( (m_flags & (exclusive | looping)) == 0
|
||||
&& sound(begin).buffer == null_handle) {
|
||||
insert( main );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -430,35 +430,35 @@ sound_source::play_combined() {
|
||||
if( soundpoint < soundchunk.second.fadein ) { break; }
|
||||
if( soundpoint >= soundchunk.second.fadeout ) { continue; }
|
||||
|
||||
if( soundchunk.first.buffer == null_handle || ( (m_flags & (sound_flags::exclusive | sound_flags::looping)) != 0
|
||||
if( soundchunk.first.buffer == null_handle || ( (m_flags & (exclusive | looping)) != 0
|
||||
&& soundchunk.first.playing > 0 ) ) {
|
||||
// combined sounds only play looped, single copy of each activated chunk
|
||||
continue;
|
||||
}
|
||||
|
||||
if( idx > 0 ) {
|
||||
insert( sound_id::chunk | idx );
|
||||
insert( chunk | idx );
|
||||
}
|
||||
else {
|
||||
// initial chunk requires some safety checks if the optional bookend is present,
|
||||
// so we don't queue another instance while the bookend is still playing
|
||||
if( sound( sound_id::begin ).buffer == null_handle ) {
|
||||
if( sound( begin ).buffer == null_handle ) {
|
||||
// no bookend, safe to play the chunk
|
||||
insert( sound_id::chunk | idx );
|
||||
insert( chunk | idx );
|
||||
}
|
||||
else {
|
||||
// branches:
|
||||
// beginning requested, not playing; queue beginning and chunk
|
||||
// beginning not requested, not playing; queue chunk
|
||||
// otherwise skip, one instance is already in the audio queue
|
||||
if( sound( sound_id::begin ).playing == 0 ) {
|
||||
if( sound( begin ).playing == 0 ) {
|
||||
if( true == m_playbeginning ) {
|
||||
std::vector<sound_handle> sounds{ sound_id::begin, sound_id::chunk | idx };
|
||||
std::vector<sound_handle> sounds{ begin, chunk | idx };
|
||||
insert( std::begin( sounds ), std::end( sounds ) );
|
||||
m_playbeginning = false;
|
||||
}
|
||||
else {
|
||||
insert( sound_id::chunk | idx );
|
||||
insert( chunk | idx );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -482,7 +482,7 @@ sound_source::compute_combined_point() const {
|
||||
void
|
||||
sound_source::play_event() {
|
||||
|
||||
if( true == TestFlag( m_flags, sound_flags::event | sound_flags::looping ) ) {
|
||||
if( true == TestFlag( m_flags, event | looping ) ) {
|
||||
// events can potentially start scenery sounds out of the sound's audible range
|
||||
// such sounds are stopped on renderer side, but unless stopped by the simulation keep their activation flags
|
||||
// we use this to discern event-started sounds which should be re-activated if the listener gets close enough
|
||||
@@ -504,11 +504,11 @@ sound_source::stop( bool const Skipend ) {
|
||||
m_stop = true;
|
||||
|
||||
if( false == Skipend
|
||||
&& sound(sound_id::end).buffer != null_handle
|
||||
&& sound(end).buffer != null_handle
|
||||
/* && ( sound( sound_id::end ).buffer != sound( sound_id::main ).buffer ) */ // end == main can happen in malformed legacy cases
|
||||
&& sound(sound_id::end).playing < 2 ) { // allows potential single extra instance to account for longer overlapping sounds
|
||||
&& sound(end).playing < 2 ) { // allows potential single extra instance to account for longer overlapping sounds
|
||||
// spawn potentially defined sound end sample, if the emitter is currently active
|
||||
insert( sound_id::end );
|
||||
insert( end );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -523,7 +523,7 @@ sound_source::update( audio::openal_source &Source ) {
|
||||
m_stop = true;
|
||||
}
|
||||
|
||||
if( sound( sound_id::main ).buffer != null_handle ) {
|
||||
if( sound( main ).buffer != null_handle ) {
|
||||
// basic variant: single main sound, with optional bookends
|
||||
update_basic( Source );
|
||||
return;
|
||||
@@ -542,21 +542,21 @@ sound_source::update_basic( audio::openal_source &Source ) {
|
||||
|
||||
auto const soundhandle { Source.sounds[ Source.sound_index ] };
|
||||
|
||||
if( sound( sound_id::begin ).buffer != null_handle ) {
|
||||
if( sound( begin ).buffer != null_handle ) {
|
||||
// potentially a multipart sound
|
||||
// detect the moment when the sound moves from startup sample to the main
|
||||
if( true == Source.sound_change ) {
|
||||
// when it happens update active sample counters, and potentially activate the looping
|
||||
if( soundhandle == sound_id::main ) {
|
||||
update_counter( sound_id::begin, -1 );
|
||||
if( soundhandle == main ) {
|
||||
update_counter( begin, -1 );
|
||||
}
|
||||
update_counter( soundhandle, 1 );
|
||||
Source.loop( soundhandle == sound_id::main ? TestFlag(m_flags, sound_flags::looping) : false );
|
||||
Source.loop( soundhandle == main ? TestFlag(m_flags, looping) : false );
|
||||
}
|
||||
}
|
||||
|
||||
if( true == m_stop
|
||||
&& soundhandle != sound_id::end ) {
|
||||
&& soundhandle != end ) {
|
||||
// kill the sound if stop was requested, unless it's sound bookend sample
|
||||
update_counter( soundhandle, -1 );
|
||||
Source.stop();
|
||||
@@ -593,7 +593,7 @@ sound_source::update_basic( audio::openal_source &Source ) {
|
||||
auto const soundhandle { Source.sounds[ Source.sound_index ] };
|
||||
// emitter initialization
|
||||
// main sample can be optionally set to loop
|
||||
Source.loop( soundhandle == sound_id::main ? TestFlag(m_flags, sound_flags::looping) : false );
|
||||
Source.loop( soundhandle == main ? TestFlag(m_flags, looping) : false );
|
||||
Source.range( m_range );
|
||||
Source.pitch( m_pitchvariation );
|
||||
update_location();
|
||||
@@ -638,19 +638,19 @@ sound_source::update_combined( audio::openal_source &Source ) {
|
||||
|
||||
auto const soundhandle { Source.sounds[ Source.sound_index ] };
|
||||
|
||||
if( sound( sound_id::begin ).buffer != null_handle ) {
|
||||
if( sound( begin ).buffer != null_handle ) {
|
||||
// potentially a multipart sound
|
||||
// detect the moment when the sound moves from startup sample to the main
|
||||
if( true == Source.sound_change ) {
|
||||
// when it happens update active sample counters, and activate the looping
|
||||
update_counter( sound_id::begin, -1 );
|
||||
update_counter( begin, -1 );
|
||||
update_counter( soundhandle, 1 );
|
||||
Source.loop( true );
|
||||
}
|
||||
}
|
||||
|
||||
if( true == m_stop
|
||||
&& soundhandle != sound_id::end ) {
|
||||
&& soundhandle != end ) {
|
||||
// kill the sound if stop was requested, unless it's sound bookend sample
|
||||
Source.stop();
|
||||
update_counter( soundhandle, -1 );
|
||||
@@ -671,11 +671,11 @@ sound_source::update_combined( audio::openal_source &Source ) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
if( ( soundhandle & sound_id::chunk ) != 0 ) {
|
||||
if( ( soundhandle & chunk ) != 0 ) {
|
||||
// for sound chunks, test whether the chunk should still be active given current value of the controlling variable
|
||||
if( ( m_flags & ( sound_flags::exclusive | sound_flags::looping ) ) != 0 ) {
|
||||
if( ( m_flags & ( exclusive | looping ) ) != 0 ) {
|
||||
auto const soundpoint { compute_combined_point() };
|
||||
auto const &soundchunk { m_soundchunks[ soundhandle ^ sound_id::chunk ] };
|
||||
auto const &soundchunk { m_soundchunks[ soundhandle ^ chunk ] };
|
||||
if( soundpoint < soundchunk.second.fadein
|
||||
|| soundpoint >= soundchunk.second.fadeout ) {
|
||||
Source.stop();
|
||||
@@ -709,9 +709,9 @@ sound_source::update_combined( audio::openal_source &Source ) {
|
||||
// the emitter wasn't yet started
|
||||
auto const soundhandle { Source.sounds[ Source.sound_index ] };
|
||||
// emitter initialization
|
||||
if( soundhandle != sound_id::begin
|
||||
&& soundhandle != sound_id::end
|
||||
&& true == TestFlag(m_flags, sound_flags::looping) ) {
|
||||
if( soundhandle != begin
|
||||
&& soundhandle != end
|
||||
&& true == TestFlag(m_flags, looping) ) {
|
||||
// main sample can be optionally set to loop
|
||||
Source.loop( true );
|
||||
}
|
||||
@@ -747,7 +747,7 @@ sound_source::update_combined( audio::openal_source &Source ) {
|
||||
void
|
||||
sound_source::update_crossfade( sound_handle const Chunk ) {
|
||||
|
||||
if( ( Chunk & sound_id::chunk ) == 0 ) {
|
||||
if( ( Chunk & chunk ) == 0 ) {
|
||||
// bookend sounds are played at their base pitch
|
||||
m_properties.pitch = 1.f;
|
||||
return;
|
||||
@@ -756,7 +756,7 @@ sound_source::update_crossfade( sound_handle const Chunk ) {
|
||||
auto const soundpoint { compute_combined_point() };
|
||||
|
||||
// NOTE: direct access to implementation details ahead, kinda fugly
|
||||
auto const chunkindex { Chunk ^ sound_id::chunk };
|
||||
auto const chunkindex { Chunk ^ chunk };
|
||||
auto const &chunkdata { m_soundchunks[ chunkindex ].second };
|
||||
|
||||
// relative pitch adjustment
|
||||
@@ -862,14 +862,14 @@ bool
|
||||
sound_source::empty() const {
|
||||
|
||||
// NOTE: we test only the main sound, won't bother playing potential bookends if this is missing
|
||||
return sound(sound_id::main).buffer == null_handle && m_soundchunksempty;
|
||||
return sound(main).buffer == null_handle && m_soundchunksempty;
|
||||
}
|
||||
|
||||
// returns true if the source is emitting any sound
|
||||
bool
|
||||
sound_source::is_playing( bool const Includesoundends ) const {
|
||||
|
||||
auto isplaying { sound(sound_id::begin).playing > 0 || sound(sound_id::main).playing > 0 };
|
||||
auto isplaying { sound(begin).playing > 0 || sound(main).playing > 0 };
|
||||
if( false == isplaying
|
||||
&& false == m_soundchunks.empty() ) {
|
||||
// for emitters with sample tables check also if any of the chunks is active
|
||||
@@ -887,21 +887,21 @@ sound_source::is_playing( bool const Includesoundends ) const {
|
||||
bool
|
||||
sound_source::is_combined() const {
|
||||
|
||||
return !m_soundchunks.empty() && sound(sound_id::main).buffer == null_handle;
|
||||
return !m_soundchunks.empty() && sound(main).buffer == null_handle;
|
||||
}
|
||||
|
||||
// returns true if specified buffer is one of the optional bookends
|
||||
bool
|
||||
sound_source::is_bookend( audio::buffer_handle const Buffer ) const {
|
||||
|
||||
return sound(sound_id::begin).buffer == Buffer || sound(sound_id::end).buffer == Buffer;
|
||||
return sound(begin).buffer == Buffer || sound(end).buffer == Buffer;
|
||||
}
|
||||
|
||||
// returns true if the source has optional bookends
|
||||
bool
|
||||
sound_source::has_bookends() const {
|
||||
|
||||
return sound(sound_id::begin).buffer != null_handle && sound(sound_id::end).buffer != null_handle;
|
||||
return sound(begin).buffer != null_handle && sound(end).buffer != null_handle;
|
||||
}
|
||||
|
||||
// returns location of the sound source in simulation region space
|
||||
@@ -1023,11 +1023,11 @@ sound_source::insert( sound_handle const Sound ) {
|
||||
sound_source::sound_data &
|
||||
sound_source::sound( sound_handle const Sound ) {
|
||||
|
||||
return (Sound & sound_id::chunk) == sound_id::chunk ? m_soundchunks[Sound ^ sound_id::chunk].first : m_sounds[Sound];
|
||||
return (Sound & chunk) == chunk ? m_soundchunks[Sound ^ chunk].first : m_sounds[Sound];
|
||||
}
|
||||
|
||||
sound_source::sound_data const &
|
||||
sound_source::sound( sound_handle const Sound ) const {
|
||||
|
||||
return (Sound & sound_id::chunk) == sound_id::chunk ? m_soundchunks[Sound ^ sound_id::chunk].first : m_sounds[Sound];
|
||||
return (Sound & chunk) == chunk ? m_soundchunks[Sound ^ chunk].first : m_sounds[Sound];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user