#define AUDIO_FLAG_ONESHOT 0x2
#define AUDIO_FLAG_SPACIAL_3D 0x4
#define AUDIO_FLAG_AUTO_START 0x8
+#define AUDIO_FLAG_KILL 0x10
#define FADEOUT_LENGTH 1100
#define FADEOUT_DIVISOR (1.0f/(float)FADEOUT_LENGTH)
#define AUDIO_DECODE_SIZE (1024*256) /* 256 kb decoding buffers */
+enum audio_source_mode
+{
+ k_audio_source_mono,
+ k_audio_source_compressed,
+};
+
typedef struct audio_clip audio_clip;
struct audio_clip
{
const char *path;
+ enum audio_source_mode source_mode;
+
void *data;
u32 size;
};
src->player->active_entity = entid;
}
- /* Setup vorbis decoder */
- struct active_audio_player *aap = &vg_audio.active_players[ entid ];
-
- stb_vorbis_alloc alloc = {
- .alloc_buffer = (char *)audio_entity_vorbis_ptr( entid ),
- .alloc_buffer_length_in_bytes = AUDIO_DECODE_SIZE
- };
+ if( src->info.source->source_mode == k_audio_source_compressed )
+ {
+ /* Setup vorbis decoder */
+ struct active_audio_player *aap = &vg_audio.active_players[ entid ];
+
+ stb_vorbis_alloc alloc = {
+ .alloc_buffer = (char *)audio_entity_vorbis_ptr( entid ),
+ .alloc_buffer_length_in_bytes = AUDIO_DECODE_SIZE
+ };
- int err;
- stb_vorbis *decoder = stb_vorbis_open_memory(
- src->info.source->data,
- src->info.source->size, &err, &alloc );
+ int err;
+ stb_vorbis *decoder = stb_vorbis_open_memory(
+ src->info.source->data,
+ src->info.source->size, &err, &alloc );
- if( !decoder )
- {
- vg_error( "stb_vorbis_open_memory failed on '%s' (%d)\n",
- src->info.source->path, err );
+ if( !decoder )
+ {
+ vg_error( "stb_vorbis_open_memory failed on '%s' (%d)\n",
+ src->info.source->path, err );
- audio_entity_free_internal( entid );
- return;
+ audio_entity_free_internal( entid );
+ return;
+ }
+ else
+ {
+ ent->length = stb_vorbis_stream_length_in_samples( decoder );
+ }
+
+ aap->vorbis_handle = decoder;
}
else
{
- ent->length = stb_vorbis_stream_length_in_samples( decoder );
+ ent->length = src->info.source->size;
}
-
- aap->vorbis_handle = decoder;
}
/*
if( aap->ent.player->enqued == 0 )
{
aap->ent.info = aap->ent.player->info;
+
+ if( (aap->ent.info.flags & AUDIO_FLAG_KILL) && !aap->ent.fadeout )
+ {
+ aap->ent.fadeout = FADEOUT_LENGTH;
+ aap->ent.fadeout_current = FADEOUT_LENGTH;
+ }
}
}
}
}
}
-VG_STATIC void audio_decode_uncompressed_mono( float *src, u32 count, float *dst )
+VG_STATIC void audio_decode_uncompressed_mono( i16 *src, u32 count, float *dst )
{
for( u32 i=0; i<count; i++ )
{
- dst[ i*2 + 0 ] = src[i];
- dst[ i*2 + 1 ] = src[i];
+ dst[ i*2 + 0 ] = (float)src[i] * (1.0f/32767.0f);
+ dst[ i*2 + 1 ] = (float)src[i] * (1.0f/32767.0f);
}
}
return n;
}
+/*
+ * ........ more wrecked code sorry!
+ */
+VG_STATIC int
+stb_vorbis_get_samples_i16_interleaved_mono( stb_vorbis *f, i16 *buffer,
+ int len )
+{
+ int n = 0,
+ c = VG_MIN( 1, f->channels - 1 );
+
+ while( n < len )
+ {
+ int k = f->channel_buffer_end - f->channel_buffer_start;
+
+ if( n+k >= len )
+ k = len - n;
+
+ for( int j=0; j < k; ++j )
+ {
+ float sl = f->channel_buffers[ 0 ][f->channel_buffer_start+j],
+ sr = f->channel_buffers[ c ][f->channel_buffer_start+j];
+
+ *buffer++ = vg_clampf( 0.5f*(sl+sr), -1.0f, 1.0f ) * 32767.0f;
+ //*buffer++ = vg_clampf( sr, -1.0f, 1.0f ) * 32767.0f;
+ }
+
+ n += k;
+ f->channel_buffer_start += k;
+
+ if( n == len )
+ break;
+
+ if( !stb_vorbis_get_frame_float( f, NULL, NULL ))
+ break;
+ }
+
+ return n;
+}
+
VG_STATIC void audio_entity_get_samples( aatree_ptr id, u32 count, float *buf )
{
vg_profile_begin( &_vg_prof_audio_decode );
float *dst = &buf[ buffer_pos * 2 ];
- int read_samples = stb_vorbis_get_samples_float_interleaved_stereo(
- aap->vorbis_handle,
- dst,
- samples_this_run );
-
- if( read_samples != samples_this_run )
+ int source_mode = ent->info.source->source_mode;
+
+ if( source_mode == k_audio_source_mono )
+ {
+ i16 *src = &((i16 *)ent->info.source->data)[ cursor ];
+ audio_decode_uncompressed_mono( src, samples_this_run, dst );
+ }
+ else if( source_mode == k_audio_source_compressed )
{
- vg_warn( "Invalid samples read (%s)\n", ent->info.source->path );
+ int read_samples = stb_vorbis_get_samples_float_interleaved_stereo(
+ aap->vorbis_handle,
+ dst,
+ samples_this_run );
+
+ if( read_samples != samples_this_run )
+ {
+ vg_warn( "Invalid samples read (%s)\n", ent->info.source->path );
+ }
}
cursor += samples_this_run;
if( (ent->info.flags & AUDIO_FLAG_LOOP) && remaining )
{
- stb_vorbis_seek_start( aap->vorbis_handle );
+ if( source_mode == k_audio_source_compressed )
+ {
+ stb_vorbis_seek_start( aap->vorbis_handle );
+ }
+
cursor = 0;
continue;
}
VG_STATIC void audio_clip_load( audio_clip *clip )
{
- clip->data = vg_file_read( vg_audio.audio_pool, clip->path );
- clip->size = vg_file_size( vg_audio.audio_pool );
+ if( clip->source_mode == k_audio_source_mono )
+ {
+ vg_linear_clear( vg_mem.scratch );
+ u32 fsize;
+ void *filedata = vg_file_read( vg_mem.scratch, clip->path, &fsize );
+
+ stb_vorbis_alloc alloc = {
+ .alloc_buffer = vg_linear_alloc( vg_mem.scratch, AUDIO_DECODE_SIZE ),
+ .alloc_buffer_length_in_bytes = AUDIO_DECODE_SIZE
+ };
+
+ int err;
+ stb_vorbis *decoder = stb_vorbis_open_memory(
+ filedata, fsize, &err, &alloc );
+
+ if( !decoder )
+ {
+ vg_error( "stb_vorbis_open_memory failed on '%s' (%d)\n",
+ clip->path, err );
+ vg_fatal_exit_loop( "Vorbis decode error" );
+ }
+
+ /* only mono is supported in uncompressed */
+ u32 length_samples = stb_vorbis_stream_length_in_samples( decoder ),
+ data_size = length_samples * sizeof(i16);
+
+ clip->data = vg_linear_alloc( vg_audio.audio_pool, data_size );
+ clip->size = length_samples;
- if( !clip->data )
- vg_fatal_exit_loop( "Audio failed to load" );
+ int read_samples = stb_vorbis_get_samples_i16_interleaved_mono(
+ decoder, clip->data, length_samples );
- float mb = (float)(clip->size) / (1024.0f*1024.0f);
- vg_info( "Loaded audio clip '%s' (%.1fmb)\n", clip->path, mb );
+ float mb = (float)(data_size) / (1024.0f*1024.0f);
+ vg_info( "Loaded audio clip '%s' (%.1fmb)\n", clip->path, mb );
+ }
+
+ /* load in directly */
+ else if( clip->source_mode == k_audio_source_compressed )
+ {
+ clip->data = vg_file_read( vg_audio.audio_pool, clip->path, &clip->size );
+
+ if( !clip->data )
+ vg_fatal_exit_loop( "Audio failed to load" );
+
+ float mb = (float)(clip->size) / (1024.0f*1024.0f);
+ vg_info( "Loaded audio clip '%s' (%.1fmb)\n", clip->path, mb );
+ }
}
VG_STATIC void audio_clip_loadn( audio_clip *arr, int count )
audio_require_init( player );
audio_require_clip_loaded( clip );
+ if( player->info.flags & AUDIO_FLAG_KILL )
+ {
+ vg_error( "Can't start audio clip on player that is/has disconnected" );
+ return;
+ }
+
player->info.source = clip;
audio_player_commit( player );
}