#include "vg/vg_profiler.h"
#include <sys/time.h>
+#include <math.h>
#ifdef __GNUC__
#ifndef __clang__
v3f listener_pos,
listener_ears;
+
+ float volume,
+ volume_target,
+ volume_target_internal,
+ volume_console;
}
-vg_audio;
+vg_audio = { .volume_console = 1.0f };
static struct vg_profile
_vg_prof_audio_decode = {.mode = k_profile_mode_accum,
.persistent = 1
});
+ vg_convar_push( (struct vg_convar){
+ .name = "volume",
+ .data = &vg_audio.volume_console,
+ .data_type = k_convar_dtype_f32,
+ .opt_f32 = { .min=0.0f, .max=2.0f, .clamp=1 },
+ .persistent = 1
+ });
+
/* allocate memory */
/* 32mb fixed */
{
/* Process incoming sound queue */
audio_lock();
+
+ vg_audio.volume_target_internal = vg_audio.volume_target;
int wr = 0;
for( int i=0; i<vg_audio.queue_len; i++ )
/*
* Get effective volume and pan from this entity
*/
-VG_STATIC void audio_entity_spacialize( audio_entity *ent, float *vol, float *pan )
+VG_STATIC void audio_entity_spacialize( audio_entity *ent,
+ float *vol, float *pan )
{
if( ent->info.vol < 0.01f )
{
return;
}
+ if( !vg_validf(vg_audio.listener_pos[0]) ||
+ !vg_validf(vg_audio.listener_pos[1]) ||
+ !vg_validf(vg_audio.listener_pos[2]) ||
+ !vg_validf(ent->info.world_position[0]) ||
+ !vg_validf(ent->info.world_position[1]) ||
+ !vg_validf(ent->info.world_position[2]) )
+ {
+ vg_error( "NaN listener/world position (%s)\n", ent->name );
+ *vol = 0.0f;
+ *pan = 0.0f;
+ return;
+ }
+
v3f delta;
v3_sub( ent->info.world_position, vg_audio.listener_pos, delta );
for( u32 j=0; j<frame_count; j++ )
{
- float frame_vol = vol;
-
+ float frame_vol = vol * vg_audio.volume;
if( ent->fadeout )
{
/* Force this system to be removed now */
for( int i=0; i<frame_count*2; i ++ )
pOut32F[i] = 0.0f;
+ float start_vol = vg_audio.volume;
+
/* Mix all sounds */
for( int i=0; i<SFX_MAX_SYSTEMS; i ++ )
{
struct active_audio_player *aap = &vg_audio.active_players[i];
+ vg_audio.volume = start_vol;
if( aap->active )
- {
audio_entity_mix( i, pOut32F, frame_count );
- }
}
+ float vol_diff = vg_audio.volume_target_internal - vg_audio.volume,
+ vol_rate = 1.0f / (44100.0f*0.25f),
+ vol_chg = frame_count * vol_rate;
+
+ if( vol_chg > fabsf( vol_diff ) )
+ vg_audio.volume = vg_audio.volume_target_internal;
+ else
+ vg_audio.volume += vg_signf( vol_diff ) * vol_chg;
+
/* redistribute */
audio_system_cleanup();
audio_lock();
+
vg_profile_increment( &_vg_prof_audio_decode );
vg_profile_increment( &_vg_prof_audio_mix );
VG_STATIC void audio_player_set_vol( audio_player *sys, float vol )
{
audio_require_lock();
+
+ if( !vg_validf(vol) )
+ {
+ vg_warn( "NaN volume (%s)\n", sys->name );
+ vol = 0.0f;
+ }
+
+ if( (vol < 0.0f) || (vol > 100.0f) )
+ {
+ vg_warn( "Invalid volume (%s: %f)\n", sys->name, vol );
+ vol = 0.0f;
+ }
+
sys->info.vol = vol;
}
return sys->info.flags;
}
+VG_STATIC void audio_set_master_vol( float vol )
+{
+ audio_require_lock();
+ vg_audio.volume_target = vol;
+}
+
+VG_STATIC void audio_push_console_vol(void)
+{
+ audio_lock();
+ audio_set_master_vol( vg_audio.volume_console );
+ audio_unlock();
+}
/*
* Debugging
wpos[3] = 1.0f;
m4x4_mulv( mtx_pv, wpos, wpos );
- if( wpos[3] < 0.0f )
+ if( wpos[3] <= 0.0f )
goto projected_behind;
v2_muls( wpos, (1.0f/wpos[3]) * 0.5f, wpos );