audio subsystem: completed base functionality of the renderer, external and engine sounds moved from cab to vehicle, minor fixes to various sound-related methods

This commit is contained in:
tmj-fstate
2017-11-29 01:50:57 +01:00
parent bc43c21174
commit 3afff7c3ab
27 changed files with 2488 additions and 1929 deletions

View File

@@ -11,12 +11,15 @@ http://mozilla.org/MPL/2.0/.
#include "audiorenderer.h"
#include "sound.h"
#include "globals.h"
#include "logs.h"
namespace audio {
openal_renderer renderer;
float const EU07_SOUND_CUTOFFRANGE { 3000.f }; // 2750 m = max expected emitter spawn range, plus safety margin
// starts playback of queued buffers
void
openal_source::play() {
@@ -29,17 +32,16 @@ openal_source::play() {
void
openal_source::stop() {
::alSourcei( id, AL_LOOPING, AL_FALSE );
loop( false );
::alSourceStop( id );
// NOTE: we don't update the is_playing flag
// this way the state will change only on next update loop,
// giving the controller a chance to properly change state from cease to none
// even with multiple active sounds under control
is_playing = false;
}
// updates state of the source
void
openal_source::update( int const Deltatime ) {
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 );
@@ -58,10 +60,79 @@ openal_source::update( int const Deltatime ) {
controller->update( *this );
}
// configures state of the source to match the provided set of properties
void
openal_source::sync_with( sound_properties const &State ) {
/*
// velocity
// not used yet
glm::vec3 const velocity { ( State.location - properties.location ) / update_deltatime };
*/
// location
properties.location = State.location;
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 ) ) ) {
// range cutoff check
stop();
return;
}
if( sound_range >= 0 ) {
::alSourcefv( id, AL_POSITION, glm::value_ptr( sourceoffset ) );
}
else {
// sounds with 'unlimited' range are positioned on top of the listener
::alSourcefv( id, AL_POSITION, glm::value_ptr( glm::vec3() ) );
}
// gain
if( ( State.placement_stamp != properties.placement_stamp )
|| ( State.base_gain != properties.base_gain ) ) {
// gain value has changed
properties.base_gain = State.base_gain;
properties.placement_gain = State.placement_gain;
properties.placement_stamp = State.placement_stamp;
::alSourcef( id, AL_GAIN, properties.base_gain * properties.placement_gain * Global::AudioVolume );
}
// pitch
if( State.base_pitch != properties.base_pitch ) {
// pitch value has changed
properties.base_pitch = State.base_pitch;
::alSourcef( id, AL_PITCH, properties.base_pitch * pitch_variation );
}
}
// sets max audible distance for sounds emitted by the source
void
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
sound_range = Range;
}
// sets modifier applied to the pitch of sounds emitted by the source
void
openal_source::pitch( float const Pitch ) {
pitch_variation = Pitch;
// invalidate current pitch value to enforce change of next syns
properties.base_pitch = -1.f;
}
// toggles looping of the sound emitted by the source
void
openal_source::loop( bool const State ) {
if( is_looping == State ) { return; }
is_looping = State;
::alSourcei(
id,
AL_LOOPING,
@@ -78,9 +149,7 @@ openal_source::clear() {
controller = nullptr;
// unqueue bound buffers:
// ensure no buffer is in use...
::alSourcei( id, AL_LOOPING, AL_FALSE );
::alSourceStop( id );
is_playing = false;
stop();
// ...prepare space for returned ids of unqueued buffers (not that we need that info)...
std::vector<ALuint> bufferids;
bufferids.resize( buffers.size() );
@@ -88,6 +157,8 @@ openal_source::clear() {
::alSourceUnqueueBuffers( id, bufferids.size(), bufferids.data() );
buffers.clear();
buffer_index = 0;
// reset properties
properties = sound_properties();
}
@@ -125,6 +196,9 @@ openal_renderer::init() {
// basic initialization failed
return false;
}
//
// ::alDistanceModel( AL_LINEAR_DISTANCE );
::alDistanceModel( AL_INVERSE_DISTANCE_CLAMPED );
// all done
m_ready = true;
return true;
@@ -141,10 +215,45 @@ openal_renderer::insert( sound_source *Controller, audio::buffer_handle const So
std::begin( buffers ), std::end( buffers ) );
}
// removes from the queue all sounds controlled by the specified sound emitter
void
openal_renderer::erase( sound_source const *Controller ) {
auto source { std::begin( m_sources ) };
while( source != std::end( m_sources ) ) {
if( source->controller == Controller ) {
// if the controller is the one specified, kill it
source->clear();
m_sourcespares.push( *source );
source = m_sources.erase( source );
}
else {
// otherwise proceed through the list normally
++source;
}
}
}
// updates state of all active emitters
void
openal_renderer::update( int const Deltatime ) {
openal_renderer::update( double const Deltatime ) {
// update listener
glm::dmat4 cameramatrix;
Global::pCamera->SetMatrix( cameramatrix );
auto rotationmatrix { glm::mat3{ cameramatrix } };
glm::vec3 const orientation[] = {
glm::vec3{ 0, 0,-1 } * rotationmatrix ,
glm::vec3{ 0, 1, 0 } * rotationmatrix };
::alListenerfv( AL_ORIENTATION, reinterpret_cast<ALfloat const *>( orientation ) );
/*
glm::dvec3 const listenerposition { Global::pCameraPosition };
// not used yet
glm::vec3 const velocity { ( listenerposition - m_listenerposition ) / Deltatime };
m_listenerposition = listenerposition;
*/
// update active emitters
auto source { std::begin( m_sources ) };
while( source != std::end( m_sources ) ) {
// update each source