jeieiejieje
authorhgn <hgodden00@gmail.com>
Mon, 3 Mar 2025 14:40:11 +0000 (14:40 +0000)
committerhgn <hgodden00@gmail.com>
Mon, 3 Mar 2025 14:40:11 +0000 (14:40 +0000)
submodules/SDL_GameControllerDB
submodules/anyascii
submodules/qoi
submodules/stb
vg_audio.c
vg_audio.h

index c5b4df0e1061175cb11e3ebbf8045178339864a5..6ed8d054340ee8a93a684e11360b66cd8a5c168e 160000 (submodule)
@@ -1 +1 @@
-Subproject commit c5b4df0e1061175cb11e3ebbf8045178339864a5
+Subproject commit 6ed8d054340ee8a93a684e11360b66cd8a5c168e
index eb5332d0b5e48d58397e6f27475a18e058330d23..44e971c774d9ec67ca6c1f16c5a476724821ab63 160000 (submodule)
@@ -1 +1 @@
-Subproject commit eb5332d0b5e48d58397e6f27475a18e058330d23
+Subproject commit 44e971c774d9ec67ca6c1f16c5a476724821ab63
index dfc056e813c98d307238d35f7f041a725d699dfc..b8d77df1e80b652a57f0b7270449b179a6b91f40 160000 (submodule)
@@ -1 +1 @@
-Subproject commit dfc056e813c98d307238d35f7f041a725d699dfc
+Subproject commit b8d77df1e80b652a57f0b7270449b179a6b91f40
index 5736b15f7ea0ffb08dd38af21067c314d6a3aae9..8b5f1f37b5b75829fc72d38e7b5d4bcbf8a26d55 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 5736b15f7ea0ffb08dd38af21067c314d6a3aae9
+Subproject commit 8b5f1f37b5b75829fc72d38e7b5d4bcbf8a26d55
index 2ff5dcf0801e95107fecc54ac5ef089706f1c559..f85bd996f1fb2d81d77d559588458326f289c1cd 100644 (file)
@@ -87,96 +87,6 @@ static void audio_require_lock(void)
 #define AUDIO_EDIT_OWNERSHIP      0x40
 #define AUDIO_EDIT_SAMPLING_RATE  0x80
 
-void audio_channel_init( audio_channel *ch, audio_clip *clip, u32 flags )
-{
-   audio_require_lock();
-   ch->group = 0;
-   ch->clip = clip;
-   ch->flags = flags;
-   ch->colour = 0x00333333;
-
-   if( (ch->clip->flags & AUDIO_FLAG_FORMAT) == k_audio_format_bird )
-      strcpy( ch->name, "[array]" );
-   else if( (ch->clip->flags & AUDIO_FLAG_FORMAT) == k_audio_format_gen )
-      strcpy( ch->name, "[program]" );
-   else
-      vg_strncpy( clip->path, ch->name, 32, k_strncpy_always_add_null );
-
-   ch->allocated = 1;
-
-   ch->editable_state.relinquished = 0;
-   ch->editable_state.volume = 1.0f;
-   ch->editable_state.volume_target = 1.0f;
-   ch->editable_state.pan = 0.0f;
-   ch->editable_state.pan_target = 0.0f;
-   ch->editable_state.volume_rate = 0;
-   ch->editable_state.pan_rate = 0;
-   v4_copy((v4f){0.0f,0.0f,0.0f,1.0f},ch->editable_state.spacial_falloff);
-   ch->editable_state.lfo = NULL;
-   ch->editable_state.lfo_amount = 0.0f;
-   ch->editable_state.sampling_rate = 1.0f;
-   ch->editble_state_write_mask = 0x00;
-}
-
-void audio_channel_group( audio_channel *ch, u16 group )
-{
-   audio_require_lock();
-   ch->group = group;
-   ch->colour = (((u32)group * 29986577) & 0x00ffffff) | 0xff000000;
-}
-
-audio_channel *audio_get_first_idle_channel(void)
-{
-   audio_require_lock();
-   for( int i=0; i<AUDIO_CHANNELS; i++ ){
-      audio_channel *ch = &vg_audio.channels[i];
-
-      if( !ch->allocated ){
-         return ch;
-      }
-   }
-
-   return NULL;
-}
-
-audio_channel *audio_get_group_idle_channel( u16 group, u32 max_count )
-{
-   audio_require_lock();
-   u32 count = 0;
-   audio_channel *dest = NULL;
-
-   for( int i=0; i<AUDIO_CHANNELS; i++ ){
-      audio_channel *ch = &vg_audio.channels[i];
-
-      if( ch->allocated ){
-         if( ch->group == group ){
-            count ++;
-         }
-      }
-      else{
-         if( !dest )
-            dest = ch;
-      }
-   }
-
-   if( dest && (count < max_count) ){
-      return dest;
-   }
-
-   return NULL;
-}
-
-audio_channel *audio_get_group_first_active_channel( u16 group )
-{
-   audio_require_lock();
-   for( int i=0; i<AUDIO_CHANNELS; i++ ){
-      audio_channel *ch = &vg_audio.channels[i];
-      if( ch->allocated && (ch->group == group) )
-         return ch;
-   }
-   return NULL;
-}
-
 int audio_channel_finished( audio_channel *ch )
 {
    audio_require_lock();
@@ -186,160 +96,6 @@ int audio_channel_finished( audio_channel *ch )
       return 0;
 }
 
-audio_channel *audio_relinquish_channel( audio_channel *ch )
-{
-   audio_require_lock();
-   ch->editable_state.relinquished = 1;
-   ch->editble_state_write_mask |= AUDIO_EDIT_OWNERSHIP;
-   return NULL;
-}
-
-void audio_channel_slope_volume( audio_channel *ch, f32 length, f32 new_vol )
-{
-   audio_require_lock();
-   ch->editable_state.volume_target = new_vol;
-   ch->editable_state.volume_rate   = length * 44100.0f;
-   ch->editble_state_write_mask |= AUDIO_EDIT_VOLUME_SLOPE;
-}
-
-void audio_channel_set_sampling_rate( audio_channel *ch, float rate )
-{
-   audio_require_lock();
-   ch->editable_state.sampling_rate = rate;
-   ch->editble_state_write_mask |= AUDIO_EDIT_SAMPLING_RATE;
-}
-
-/* Review: this is never called with instant set to 1 */
-void audio_channel_edit_volume( audio_channel *ch, f32 new_vol, int instant )
-{
-   audio_require_lock();
-   if( instant )
-   {
-      ch->editable_state.volume = new_vol;
-      ch->editble_state_write_mask |= AUDIO_EDIT_VOLUME;
-   }
-   else
-   {
-      audio_channel_slope_volume( ch, 0.05f, new_vol );
-   }
-}
-
-audio_channel *audio_channel_fadeout( audio_channel *ch, float length )
-{
-   audio_require_lock();
-   audio_channel_slope_volume( ch, length, 0.0f );
-   return audio_relinquish_channel( ch );
-}
-
-void audio_channel_fadein( audio_channel *ch, float length )
-{
-   audio_require_lock();
-   audio_channel_edit_volume( ch, 0.0f, 1 );
-   audio_channel_slope_volume( ch, length, 1.0f );
-}
-
-audio_channel *audio_channel_crossfade( audio_channel *ch, 
-                                        audio_clip *new_clip,
-                                        float length, u32 flags )
-{
-   audio_require_lock();
-   u32 cursor = 0;
-
-   if( ch )
-      ch = audio_channel_fadeout( ch, length );
-
-   audio_channel *replacement = audio_get_first_idle_channel();
-
-   if( replacement ){
-      audio_channel_init( replacement, new_clip, flags );
-      audio_channel_fadein( replacement, length );
-   }
-
-   return replacement;
-}
-
-void audio_channel_sidechain_lfo( audio_channel *ch, int lfo_id, f32 amount )
-{
-   audio_require_lock();
-   ch->editable_state.lfo = &vg_audio.oscillators[ lfo_id ];
-   ch->editable_state.lfo_amount = amount;
-   ch->editble_state_write_mask |= AUDIO_EDIT_LFO_ATTACHMENT;
-}
-
-void audio_channel_set_spacial( audio_channel *ch, v3f co, float range )
-{
-   audio_require_lock();
-   if( ch->flags & AUDIO_FLAG_SPACIAL_3D ){
-      v3_copy( co, ch->editable_state.spacial_falloff );
-
-      if( range == 0.0f )
-         ch->editable_state.spacial_falloff[3] = 1.0f;
-      else
-         ch->editable_state.spacial_falloff[3] = 1.0f/range;
-
-      ch->editble_state_write_mask |= AUDIO_EDIT_SPACIAL;
-   }
-   else{
-      vg_warn( "Tried to set spacialization paramaters for 2D channel (%s)\n",
-               ch->name );
-   }
-}
-
-audio_channel *audio_oneshot_3d( audio_clip *clip, v3f position, 
-                                 f32 range, f32 volume )
-{
-   audio_require_lock();
-   audio_channel *ch = audio_get_first_idle_channel();
-
-   if( ch )
-   {
-      audio_channel_init( ch, clip, AUDIO_FLAG_SPACIAL_3D );
-      audio_channel_set_spacial( ch, position, range );
-      audio_channel_edit_volume( ch, volume, 1 );
-      audio_relinquish_channel( ch );
-
-      return ch;
-   }
-   else
-      return NULL;
-}
-
-audio_channel *audio_oneshot( audio_clip *clip, f32 volume, f32 pan )
-{
-   audio_require_lock();
-   audio_channel *ch = audio_get_first_idle_channel();
-
-   if( ch )
-   {
-      audio_channel_init( ch, clip, AUDIO_FLAG_NO_DSP );
-      audio_channel_edit_volume( ch, volume, 1 );
-      audio_relinquish_channel( ch );
-
-      return ch;
-   }
-   else
-      return NULL;
-}
-
-void audio_set_lfo_wave( int id, enum lfo_wave_type type, f32 coefficient )
-{
-   audio_require_lock();
-   audio_lfo *lfo = &vg_audio.oscillators[ id ];
-   lfo->editable_state.polynomial_coefficient = coefficient;
-   lfo->editable_state.wave_type = type;
-
-   lfo->editble_state_write_mask |= AUDIO_EDIT_LFO_WAVE;
-}
-
-void audio_set_lfo_frequency( int id, float freq )
-{
-   audio_require_lock();
-   audio_lfo *lfo = &vg_audio.oscillators[ id ];
-   lfo->editable_state.period = 44100.0f / freq;
-   lfo->editble_state_write_mask |= AUDIO_EDIT_LFO_PERIOD;
-}
-
-
 /* 
  * Committers
  * -----------------------------------------------------------------------------
@@ -1060,13 +816,288 @@ static void audio_require_clip_loaded( audio_clip *clip )
 
 
 
+_Thread_local static bool _vg_audio_thread_has_lock = 0;
+
+void vg_audio_lock(void)
+{
+   SDL_LockMutex( _vg_audio.mutex );
+   _vg_audio_thread_has_lock = 1;
+}
+
+void vg_audio_unlock(void)
+{
+   _vg_audio_thread_has_lock = 0;
+   SDL_UnlockMutex( _vg_audio.mutex );
+}
+
+static void vg_audio_assert_lock(void)
+{
+   if( _vg_audio_thread_has_lock == 0 )
+   {
+      vg_error( "vg_audio function requires locking\n" );
+      abort();
+   }
+}
 
 
+/* main channels
+ * ---------------------------------------------------------------------------------------- */
 
+audio_channel *audio_get_first_idle_channel(void)
+{
+   vg_audio_assert_lock();
+   for( int i=0; i<AUDIO_CHANNELS; i++ )
+   {
+      audio_channel *channel = &_vg_audio.channels[i];
 
+      if( channel->activity == k_channel_activity_none )
+      {
+         channel->activity = k_channel_activity_allocating;
+         channel->ui_name[0] = 0;
+         channel->ui_colour[0] = 0x00333333;
+         channel->flags = 0x00;
+         channel->group = 0;
+         channel->clip = NULL;
+         channel->clip_length = 0;
+         channel->decoder_handle.bird = NULL;
+         channel->cursor = 0;
+         channel->volume = AUDIO_VOLUME_100;
+         channel->volume_target = AUDIO_VOLUME_100;
+         channel->volume_slew_rate_per_sample = AUDIO_VOLUME_100 / (44100*10);  /* 1/10th second */
+         channel->pan = 0;
+         channel->pan_target = 0;
+         channel->pan_slew_rate_per_sample = AUDIO_PAN_RIGHT_100 / (44100*10);
+         channel->sampling_rate_multiplier = 1.0f;
+         v4_copy( (v4f){0,0,0,1}, channel->spacial_falloff );
+         channel->lfo = NULL;
+         channel->lfo_attenuation_amount = 0.0f;
+         return channel;
+      }
+   }
 
+   return NULL;
+}
 
+void vg_audio_set_channel_clip( audio_channel *channel, audio_clip *clip )
+{
+   vg_audio_assert_lock();
+   VG_ASSERT( channel->activity == k_channel_activity_allocating );
+   VG_ASSERT( channel->clip == NULL );
 
+   channel->clip = clip;
+
+   u32 audio_format = channel->clip->flags & AUDIO_FLAG_FORMAT;
+   if( audio_format == k_audio_format_bird )
+      strcpy( channel->name, "[array]" );
+   else if( audio_format == k_audio_format_gen )
+      strcpy( channel->name, "[program]" );
+   else
+      vg_strncpy( clip->path, channel->name, 32, k_strncpy_always_add_null );
+}
+
+void vg_audio_set_channel_group( audio_channel *channel, u16 group )
+{
+   vg_audio_assert_lock();
+   VG_ASSERT( channel->activity == k_channel_activity_allocating );
+   VG_ASSERT( channel->group = NULL );
+   channel->group = group;
+   if( group )
+      channel->ui_colour = (((u32)group * 29986577) & 0x00ffffff) | 0xff000000;
+}
+
+u32 vg_audio_count_channels_in_group( u16 group )
+{
+   vg_audio_assert_lock();
+
+   u32 count = 0;
+   for( int i=0; i<AUDIO_CHANNELS; i++ )
+   {
+      audio_channel *channel = &_vg_audio.channels[i];
+
+      if( channel->activity != k_channel_activity_none )
+         count ++;
+   }
+   
+   return count;
+}
+
+audio_channel *vg_audio_get_first_active_channel_in_group( u16 group )
+{
+   vg_audio_assert_lock();
+   for( int i=0; i<AUDIO_CHANNELS; i++ )
+   {
+      audio_channel *channel = &_vg_audio.channels[i];
+      if( (channel->activity != k_channel_activity_none) && (channel->group == group) )
+         return channel;
+   }
+   return NULL;
+}
+
+void vg_audio_sidechain_lfo_to_channel( audio_channel *channel, audio_lfo *lfo, f32 amount )
+{
+   vg_audio_assert_lock();
+   channel->lfo = lfo;
+   channel->lfo_attenuation_amount = ammount;
+}
+
+void vg_audio_set_channel_spacial_falloff( audio_channel *channel, v3f co, f32 range )
+{
+   vg_audio_assert_lock();
+   channel->flags |= AUDIO_FLAG_SPACIAL_3D;
+   v3_copy( co, channel->spacial_falloff );
+   channel->spacial_falloff[3] = range == 0.0f? 1.0f: 1.0f/range;
+}
+
+void vg_audio_set_channel_volume( audio_channel *channel, f64 volume, bool instant )
+{
+   vg_audio_assert_lock();
+   channel->volume_target = ((f64)AUDIO_VOLUME_100) * volume;
+
+   if( instant )
+      channel->volume = channel->volume_target;
+}
+
+void vg_audio_set_channel_volume_slew_duration( audio_channel *channel, f64 length_seconds )
+{
+   vg_audio_assert_lock();
+   channel->volume_slew_rate_per_sample = (f64)AUDIO_VOLUME_100 / (length_seconds * 44100.0);
+}
+
+void vg_audio_set_channel_pan_slew_duration( audio_channel *channel, f64 length_seconds )
+{
+   vg_audio_assert_lock();
+   channel->pan_slew_rate_per_sample = (f64)AUDIO_PAN_RIGHT_100 / (length_seconds * 44100.0);
+}
+
+void vg_audio_relinquish_channel( audio_channel *channel )
+{
+   vg_audio_assert_lock();
+   channel->flags |= AUDIO_FLAG_RELINQUISHED;
+}
+
+void vg_audio_channel_start( audio_channel *channel )
+{
+   vg_audio_assert_lock();
+   VG_ASSERT( channel->activity == k_channel_activity_allocation );
+   VG_ASSERT( channel->clip );
+   channel->activity = k_channel_activity_wake;
+}
+
+audio_channel *vg_audio_crossfade( audio_channel *channel, audio_clip *new_clip, f32 transition_seconds )
+{
+   vg_audio_assert_lock();
+   VG_ASSERT( channel );
+
+   vg_audio_set_channel_volume_slew_duration( channel, transition_seconds );
+   vg_audio_set_channel_volume( channel, 0.0 );
+   vg_audio_relinquish_channel( channel );
+
+   audio_channel *replacement = vg_audio_get_first_idle_channel();
+
+   if( replacement )
+   {
+      vg_audio_set_channel_clip( replacement, new_clip );
+      vg_audio_set_channel_volume_slew_duration( replacement, transition_seconds );
+      vg_audio_set_channel_volume( replacement, 1.0 );
+      vg_audio_set_channel_group( replacement, channel->group );
+      replacement->flags = channel->flags;
+      replacement->lfo = channel->lfo;
+      replacement->lfo_attenuation_amount = channel->attenuation_amount;
+      v4_copy( channel->spacial_falloff, replacement->spacial_falloff );
+      vg_audio_channel_start( replacement );
+   }
+
+   return replacement;
+}
+
+void vg_audio_oneshot_3d( audio_clip *clip, v3f co, f32 range, f32 volume, u16 group )
+{
+   vg_audio_assert_lock();
+   audio_channel *channel = vg_audio_get_first_idle_channel();
+
+   if( channel )
+   {
+      vg_audio_set_channel_clip( channel, clip );
+      vg_audio_set_channel_spacial_falloff( channel, co, range );
+      vg_audio_set_channel_group( channel, group );
+      vg_audio_set_
+      vg_audio_start_channel( channel );
+
+      audio_channel_edit_volume( ch, volume, 1 );
+      audio_relinquish_channel( ch );
+   }
+}
+
+audio_channel *audio_oneshot( audio_clip *clip, f32 volume, f32 pan )
+{
+   audio_require_lock();
+   audio_channel *ch = audio_get_first_idle_channel();
+
+   if( ch )
+   {
+      audio_channel_init( ch, clip, AUDIO_FLAG_NO_DSP );
+      audio_channel_edit_volume( ch, volume, 1 );
+      audio_relinquish_channel( ch );
+
+      return ch;
+   }
+   else
+      return NULL;
+}
+
+
+
+/* lfos
+ * ---------------------------------------------------------------------------------------- */
+
+audio_lfo *vg_audio_get_first_idle_lfo(void)
+{
+   vg_audio_assert_lock();
+
+   for( int i=0; i<AUDIO_LFOS; i++ )
+   {
+      audio_lfo *lfo = &_vg_audio.lfos[i];
+
+      if( lfo->activity == k_channel_activity_none )
+      {
+         lfo->activity = k_channel_activity_allocation;
+         lfo->time = 0;
+         lfo->period_in_samples = 44100;
+         lfo->last_period_in_samples = 4410;
+         lfo->wave_type = k_lfo_triangle;
+         lfo->polynomial_coefficient = 0.0f;
+         lfo->flags = 0x00;
+         return lfo;
+      }
+   }
+
+   return NULL;
+}
+
+void vg_audio_set_lfo_polynomial_bipolar( audio_lfo *lfo, f32 coefficient )
+{
+   vg_audio_assert_lock();
+
+   lfo->polynomial_coefficient = coefficient;
+   lfo->wave_type = k_lfo_polynomial_bipolar;
+}
+
+void vg_audio_set_lfo_frequency( audio_lfo *lfo, f32 freq )
+{
+   vg_audio_assert_lock();
+
+   u32 length = 44100.0f / freq;
+   lfo->period_in_samples = length;
+
+   if( lfo->activity == k_channel_activity_allocation )
+      lfo->last_period_in_samples = length;
+}
+
+void vg_audio_start_lfo( audio_lfo *lfo )
+{
+   vg_audio_assert_lock();
+   lfo->activity = k_achannel_activity_alive;
+}
 
 
 
@@ -1265,16 +1296,6 @@ void vg_audio_register(void)
    vg_console_reg_var( "vg_dsp", &_vg_audio.dsp_enabled, k_var_dtype_i32, VG_VAR_PERSISTENT );
 }
 
-void audio_lock(void)
-{
-   SDL_LockMutex( _vg_audio.mutex );
-}
-
-void audio_unlock(void)
-{
-   SDL_UnlockMutex( _vg_audio.mutex );
-}
-
 void vg_audio_device_init(void)
 {
    SDL_AudioSpec spec_desired, spec_got;
index bae314bd4dae4cbfbacac467c32d8ba0544be4ec..4765a2583d9157e2a62e7cbdc411823cc4fbb8f7 100644 (file)
@@ -45,12 +45,25 @@ enum audio_format
 
 #define AUDIO_DECODE_SIZE     (1024*256)  /* 256 kb decoding buffers */
 
-#define AUDIO_VOLUME_100 500000000
+#define AUDIO_VOLUME_100      500000000
+#define AUDIO_PAN_RIGHT_100   500000000
+#define AUDIO_PAN_LEFT_100   -500000000
 
 typedef struct audio_clip audio_clip;
 typedef struct audio_channel audio_channel;
 typedef struct audio_lfo audio_lfo;
 
+enum channel_activity
+{
+   k_channel_activity_none,
+   k_channel_activity_allocation,
+   k_channel_activity_wake,
+   k_channel_activity_alive,
+   k_channel_activity_pause,
+   k_channel_activity_end,
+   k_channel_activity_error
+};
+
 struct audio_clip
 {
    union 
@@ -73,7 +86,8 @@ struct audio_clip
 
 struct audio_lfo
 {
-   u32 time, period_in_samples;
+   enum channel_activity activity;
+   u32 time, period_in_samples, last_period_in_samples;
 
    enum lfo_wave_type
    {
@@ -92,23 +106,14 @@ struct audio_lfo
 
 struct audio_channel
 {
+   enum channel_activity activity;
+
    /* properties */
    char ui_name[32];
    u32  ui_colour;
    u32 flags;
    u16 group;
 
-   enum channel_activity
-   {
-      k_channel_activity_none,
-      k_channel_activity_allocation,
-      k_channel_activity_alive,
-      k_channel_activity_pause,
-      k_channel_activity_end,
-      k_channel_activity_error
-   }
-   activity;
-
    audio_clip *clip;
    u32 clip_length;
 
@@ -168,14 +173,16 @@ void vg_audio_free(void);
 void audio_clip_load( audio_clip *clip, void *lin_alloc );
 void audio_clip_loadn( audio_clip *arr, int count, void *lin_alloc );
 
-void audio_lock(void);
-void audio_unlock(void);
+void vg_audio_lock(void);
+void vg_audio_unlock(void);
 
-void audio_channel_init( audio_channel *ch, audio_clip *clip, u32 flags );
-void audio_channel_group( audio_channel *ch, u16 group );
-audio_channel *audio_get_first_idle_channel(void);
-audio_channel *audio_get_group_idle_channel( u16 group, u32 max_count );
-audio_channel *audio_get_group_first_active_channel( u16 group );
+void vg_audio_channel_init( audio_channel *ch, audio_clip *clip, u32 flags );
+void vg_audio_channel_group( audio_channel *ch, u16 group );
+audio_channel *vg_audio_get_first_idle_channel(void);
+audio_channel *vg_audio_get_group_idle_channel( u16 group, u32 max_count );
+audio_channel *vg_audio_get_group_first_active_channel( u16 group );
+
+audio_lfo *vg_audio_get_first_idle_lfo(void);
 
 #if 0
 
@@ -306,8 +313,8 @@ void vg_audio_device_init(void);
 void vg_audio_init(void);
 void vg_audio_free(void);
 
-void audio_lock(void);
-void audio_unlock(void);
+void vg_audio_lock(void);
+void vg_audio_unlock(void);
 
 void audio_channel_init( audio_channel *ch, audio_clip *clip, u32 flags );
 void audio_channel_group( audio_channel *ch, u16 group );