float volume, /* current volume */
volume_target, /* target volume */
pan,
- pan_target;
+ pan_target,
+ sampling_rate;
u32 volume_rate,
pan_rate;
#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 )
{
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;
}
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,
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 )
{
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,
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 )
* 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 );
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 )
{