resampling rate
authorhgn <hgodden00@gmail.com>
Wed, 8 Mar 2023 03:12:47 +0000 (03:12 +0000)
committerhgn <hgodden00@gmail.com>
Wed, 8 Mar 2023 03:12:47 +0000 (03:12 +0000)
vg_audio.h

index 20972c082a4dffa21ec68d3fd21e99bc1f942567..a0d6b6b2beafc26912c6700a324c2e8581bd95ad 100644 (file)
@@ -146,7 +146,8 @@ static struct vg_audio_system
          float volume,          /* current volume */
                volume_target,   /* target volume */
                pan,
-               pan_target;
+               pan_target,
+               sampling_rate;
 
          u32   volume_rate,
                pan_rate;
@@ -306,6 +307,7 @@ VG_STATIC void vg_audio_free(void)
 #define AUDIO_EDIT_LFO_ATTACHMENT 0x10
 #define AUDIO_EDIT_SPACIAL        0x20
 #define AUDIO_EDIT_OWNERSHIP      0x40
+#define AUDIO_EDIT_SAMPLING_RATE  0x80
 
 static audio_channel *audio_request_channel( audio_clip *clip, u32 flags )
 {
@@ -331,6 +333,7 @@ static audio_channel *audio_request_channel( audio_clip *clip, u32 flags )
          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;
          return ch;
       }
@@ -346,45 +349,44 @@ static audio_channel *audio_relinquish_channel( audio_channel *ch )
    return NULL;
 }
 
-static audio_channel *audio_channel_slope_volume( audio_channel *ch, 
-                                                  float length,
-                                                  float new_volume )
+static void audio_channel_slope_volume( audio_channel *ch, float length,
+                                        float new_volume )
 {
    ch->editable_state.volume_target = new_volume;
    ch->editable_state.volume_rate   = length * 44100.0f;
    ch->editble_state_write_mask |= AUDIO_EDIT_VOLUME_SLOPE;
+}
 
-   return ch;
+static void audio_channel_set_sampling_rate( audio_channel *ch, float rate )
+{
+   ch->editable_state.sampling_rate = rate;
+   ch->editble_state_write_mask |= AUDIO_EDIT_SAMPLING_RATE;
 }
 
-static audio_channel *audio_channel_edit_volume( audio_channel *ch,
-                                                 float new_volume, int instant )
+static void audio_channel_edit_volume( audio_channel *ch,
+                                       float new_volume, int instant )
 {
    if( instant )
    {
       ch->editable_state.volume = 0.0f;
       ch->editble_state_write_mask |= AUDIO_EDIT_VOLUME;
-      return ch;
    }
    else
    {
-      return audio_channel_slope_volume( ch, 0.05f, new_volume );
+      audio_channel_slope_volume( ch, 0.05f, new_volume );
    }
 }
 
 static audio_channel *audio_channel_fadeout( audio_channel *ch, float length )
 {
-   ch = audio_channel_slope_volume( ch, length, 0.0f );
-   ch = audio_relinquish_channel( ch );
-
-   return ch;
+   audio_channel_slope_volume( ch, length, 0.0f );
+   return audio_relinquish_channel( ch );
 }
 
-static audio_channel *audio_channel_fadein( audio_channel *ch, float length )
+static void audio_channel_fadein( audio_channel *ch, float length )
 {
-   ch = audio_channel_edit_volume( ch, 0.0f, 1 );
-   ch = audio_channel_slope_volume( ch, length, 1.0f );
-   return ch;
+   audio_channel_edit_volume( ch, 0.0f, 1 );
+   audio_channel_slope_volume( ch, length, 1.0f );
 }
 
 static audio_channel *audio_channel_crossfade( audio_channel *ch, 
@@ -394,32 +396,25 @@ static audio_channel *audio_channel_crossfade( audio_channel *ch,
    u32 cursor = 0;
 
    if( ch )
-   {
       ch = audio_channel_fadeout( ch, length );
-   }
 
    audio_channel *replacement = audio_request_channel( new_clip, flags );
 
    if( replacement )
-   {
-      replacement = audio_channel_fadein( replacement, length );
-   }
+      audio_channel_fadein( replacement, length );
 
    return replacement;
 }
 
-static audio_channel *audio_channel_sidechain_lfo( audio_channel *ch,
-                                                   int lfo_id, float amount )
+static void audio_channel_sidechain_lfo( audio_channel *ch, int lfo_id,
+                                         float amount )
 {
    ch->editable_state.lfo = &vg_audio.oscillators[ lfo_id ];
    ch->editable_state.lfo_amount = amount;
    ch->editble_state_write_mask |= AUDIO_EDIT_LFO_ATTACHMENT;
-
-   return ch;
 }
 
-static audio_channel *audio_channel_set_spacial( audio_channel *ch,
-                                                 v3f co, float range )
+static void audio_channel_set_spacial( audio_channel *ch, v3f co, float range )
 {
    if( ch->flags & AUDIO_FLAG_SPACIAL_3D )
    {
@@ -432,36 +427,38 @@ static audio_channel *audio_channel_set_spacial( audio_channel *ch,
       vg_warn( "Tried to set spacialization paramaters for 2D channel (%s)\n",
                ch->name );
    }
-
-   return ch;
 }
 
-static audio_channel *audio_oneshot_3d( audio_clip *clip, v3f position, 
-                                        float range, float volume )
+static int audio_oneshot_3d( audio_clip *clip, v3f position, 
+                             float range, float volume )
 {
    audio_channel *ch = audio_request_channel( clip, AUDIO_FLAG_SPACIAL_3D );
 
    if( ch )
    {
-      ch = audio_channel_set_spacial( ch, position, range );
-      ch = audio_channel_edit_volume( ch, volume, 1 );
+      audio_channel_set_spacial( ch, position, range );
+      audio_channel_edit_volume( ch, volume, 1 );
       ch = audio_relinquish_channel( ch );
-   }
 
-   return ch;
+      return 1;
+   }
+   else
+      return 0;
 }
 
-static audio_channel *audio_oneshot( audio_clip *clip, float volume, float pan )
+static int audio_oneshot( audio_clip *clip, float volume, float pan )
 {
    audio_channel *ch = audio_request_channel( clip, 0x00 );
 
    if( ch )
    {
-      ch = audio_channel_edit_volume( ch, volume, 1 );
+      audio_channel_edit_volume( ch, volume, 1 );
       ch = audio_relinquish_channel( ch );
-   }
 
-   return ch;
+      return 1;
+   }
+   else
+      return 0;
 }
 
 static void audio_set_lfo_wave( int id, enum lfo_wave_type type, 
@@ -730,11 +727,17 @@ static void audio_channel_get_samples( audio_channel *ch,
 static void audio_channel_mix( audio_channel *ch, 
                                float *buffer, u32 frame_count )
 {
-   u32 buffer_pos = 0;
-   float *pcf = alloca( frame_count * 2 * sizeof(float) );
    u32 frames_write = frame_count;
 
-   audio_channel_get_samples( ch, frame_count, pcf );
+   u32 buffer_length = frame_count;
+   if( ch->_.sampling_rate != 1.0f )
+   {
+      buffer_length = ceilf( (float)frame_count * ch->_.sampling_rate ) + 1;
+   }
+
+   float *pcf = alloca( buffer_length * 2 * sizeof(float) );
+
+   audio_channel_get_samples( ch, buffer_length, pcf );
    vg_profile_begin( &_vg_prof_audio_mix );
 
    if( ch->_.lfo )
@@ -793,12 +796,32 @@ static void audio_channel_mix( audio_channel *ch,
                                           * ch->_.lfo_amount;
 
       float vol_l     = vol_norm * framevol_l,
-            vol_r     = vol_norm * framevol_r;
-
-      buffer[ buffer_pos*2+0 ] += pcf[ buffer_pos*2+0 ] * vol_l;
-      buffer[ buffer_pos*2+1 ] += pcf[ buffer_pos*2+1 ] * vol_r;
+            vol_r     = vol_norm * framevol_r,
+            sample_l,
+            sample_r;
       
-      buffer_pos ++;
+      if( ch->_.sampling_rate != 1.0f )
+      {
+         /* absolutely garbage resampling, but it will do
+          */
+
+         float sample_index = ch->_.sampling_rate * (float)j;
+         float t = vg_fractf( sample_index );
+
+         u32 i0 = floorf( sample_index ),
+             i1 = i0+1;
+
+         sample_l = pcf[ i0*2+0 ]*(1.0f-t) + pcf[ i1*2+0 ]*t;
+         sample_r = pcf[ i0*2+1 ]*(1.0f-t) + pcf[ i1*2+1 ]*t;
+      }
+      else
+      {
+         sample_l = pcf[ j*2+0 ];
+         sample_r = pcf[ j*2+1 ];
+      }
+
+      buffer[ j*2+0 ] += sample_l * vol_l;
+      buffer[ j*2+1 ] += sample_r * vol_r;
    }
 
    vg_profile_end( &_vg_prof_audio_mix );
@@ -865,7 +888,13 @@ VG_STATIC void audio_mixer_callback( void *user, u8 *stream, int byte_count )
          ch->editable_state.volume_target = ch->_.volume_target;
          ch->editable_state.volume_rate   = ch->_.volume_rate;
       }
-      
+
+
+      if( ch->editble_state_write_mask & AUDIO_EDIT_SAMPLING_RATE )
+         ch->_.sampling_rate = ch->editable_state.sampling_rate;
+      else
+         ch->editable_state.sampling_rate = ch->_.sampling_rate;
+
 
       if( ch->editble_state_write_mask & AUDIO_EDIT_LFO_ATTACHMENT )
       {