all changes
[vg.git] / vg_audio.h
index d5ad5d26ec422ea940dd48ab020f84988f17447e..fc09d103aa5338167100acdd0738679d656e3aba 100644 (file)
@@ -16,6 +16,7 @@
 #include "vg/vg_profiler.h"
 
 #include <sys/time.h>
+#include <math.h>
 
 #ifdef __GNUC__
   #ifndef __clang__
@@ -152,8 +153,13 @@ static struct vg_audio_system
 
    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,
@@ -219,6 +225,14 @@ VG_STATIC void vg_audio_init(void)
       .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 */
@@ -381,6 +395,8 @@ VG_STATIC void audio_system_enque(void)
 {
    /* 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++ )
@@ -473,7 +489,8 @@ VG_STATIC void audio_system_cleanup(void)
 /* 
  * 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 )
    {
@@ -482,6 +499,19 @@ VG_STATIC void audio_entity_spacialize( audio_entity *ent, float *vol, float *pa
       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 );
 
@@ -679,8 +709,7 @@ VG_STATIC void audio_entity_mix( aatree_ptr id, float *buffer,
 
    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 */
@@ -718,21 +747,32 @@ VG_STATIC void audio_mixer_callback( void *user, u8 *stream, int byte_count )
    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 );
 
@@ -931,6 +971,19 @@ VG_STATIC void audio_player_set_position( audio_player *sys, v3f pos )
 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;
 }
 
@@ -964,6 +1017,18 @@ VG_STATIC u32 audio_player_get_flags( audio_player *sys )
    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
@@ -1069,7 +1134,7 @@ VG_STATIC void audio_debug_ui( m4x4f mtx_pv )
             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 );