mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user