const char *path;
enum audio_source_mode source_mode;
- void *data;
u32 size;
+ void *data;
};
typedef struct audio_mix_info audio_mix_info;
/* 32mb fixed */
vg_audio.audio_pool =
- vg_create_linear_allocator( vg_mem.rtmemory, 1024*1024*32 );
+ vg_create_linear_allocator( vg_mem.rtmemory, 1024*1024*32,
+ VG_MEMORY_SYSTEM );
/* fixed */
u32 decode_size = AUDIO_DECODE_SIZE * SFX_MAX_SYSTEMS;
{
for( u32 i=0; i<count; i++ )
{
- dst[ i*2 + 0 ] = (float)src[i] * (1.0f/32767.0f);
- dst[ i*2 + 1 ] = (float)src[i] * (1.0f/32767.0f);
+ dst[ i*2 + 0 ] = ((float)src[i]) * (1.0f/32767.0f);
+ dst[ i*2 + 1 ] = ((float)src[i]) * (1.0f/32767.0f);
}
}
* ........ more wrecked code sorry!
*/
VG_STATIC int
-stb_vorbis_get_samples_i16_interleaved_mono( stb_vorbis *f, i16 *buffer,
- int len )
+stb_vorbis_get_samples_i16_downmixed( stb_vorbis *f, i16 *buffer, int len )
{
int n = 0,
c = VG_MIN( 1, f->channels - 1 );
if( source_mode == k_audio_source_mono )
{
- i16 *src = &((i16 *)ent->info.source->data)[ cursor ];
+ i16 *src_buffer = ent->info.source->data,
+ *src = &src_buffer[cursor];
+
audio_decode_uncompressed_mono( src, samples_this_run, dst );
}
else if( source_mode == k_audio_source_compressed )
}
VG_STATIC void audio_entity_mix( aatree_ptr id, float *buffer,
- u32 frame_count )
+ u32 frame_count )
{
audio_entity *ent = &vg_audio.active_players[id].ent;
{
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
};
+ void *filedata = vg_file_read( vg_mem.scratch, clip->path, &fsize );
+
int err;
stb_vorbis *decoder = stb_vorbis_open_memory(
filedata, fsize, &err, &alloc );
u32 length_samples = stb_vorbis_stream_length_in_samples( decoder ),
data_size = length_samples * sizeof(i16);
+ audio_lock();
clip->data = vg_linear_alloc( vg_audio.audio_pool, data_size );
clip->size = length_samples;
+ audio_unlock();
- int read_samples = stb_vorbis_get_samples_i16_interleaved_mono(
+ int read_samples = stb_vorbis_get_samples_i16_downmixed(
decoder, clip->data, length_samples );
+ if( read_samples != length_samples )
+ vg_fatal_exit_loop( "Decode error" );
+
float mb = (float)(data_size) / (1024.0f*1024.0f);
- vg_info( "Loaded audio clip '%s' (%.1fmb)\n", clip->path, mb );
+ vg_info( "Loaded audio clip '%s' (%.1fmb) %u samples\n", clip->path, mb,
+ length_samples );
}
/* load in directly */
else if( clip->source_mode == k_audio_source_compressed )
{
+ audio_lock();
clip->data = vg_file_read( vg_audio.audio_pool, clip->path, &clip->size );
+ audio_unlock();
if( !clip->data )
vg_fatal_exit_loop( "Audio failed to load" );
if( sys->enqued )
{
- vg_warn( "Audio commit spamming; already enqued (%s)\n", sys->name );
+ vg_warn( "[2] Audio commit spamming; already enqued (%s)\n", sys->name );
return;
}
return;
}
+ if( player->enqued )
+ {
+ vg_warn( "[1] Audio commit spamming; already enqued (%s)\n",
+ player->name );
+ return;
+ }
+
player->info.source = clip;
audio_player_commit( player );
}
#include <stdlib.h>
#include <malloc.h>
+#define VG_MAX_ALLOCATIONS 64
+#define VG_FUZZ_ALLOCATIONS
+#define VG_DEBUG_ALLOCATIONS
+
+typedef struct vg_linear_allocator vg_linear_allocator;
+typedef struct vg_allocation_meta vg_allocation_meta;
+
+struct
+{
+ void *rtmemory,
+ *scratch;
+
+ int use_libc_malloc;
+}
+static vg_mem;
+
+struct vg_allocation_meta
+{
+ void *data;
+ enum allocation_type
+ {
+ k_allocation_type_block = 0,
+ k_allocation_type_linear = 1
+ }
+ type;
+};
+
+#define VG_MEMORY_SYSTEM 0x1 /* systems memory, slow and low counts */
+#define VG_MEMORY_REALTIME 0x2 /* per-frame. no max allocs, only size. fast */
+
+/* systems memory cannot be declared inside realtime memory regions */
+
+/*
+ * Stored just behind the array. 32 bytes.
+ */
+#pragma pack(push,1)
+struct vg_linear_allocator
+{
+ u32 size;
+ /* */
+ /* */
+ /* */
+ u32 cur;
+ /* */
+ /* */
+ /* */
+ u16 allocation_count;
+ /* */
+ u16 flags;
+ /* */
+ u32 last_alloc_size;
+ /* */
+ /* */
+ /* */
+ void *last_alloc;
+ /* */
+ /* */
+ /* */
+ /* */
+ /* */
+ /* */
+ /* */
+ vg_allocation_meta *alloc_table;
+ /* */
+ /* */
+ /* */
+ /* */
+ /* */
+ /* */
+ /* */
+};
+#pragma pack(pop)
+
+VG_STATIC void vg_error(const char *fmt, ...);
+VG_STATIC void vg_info(const char *fmt, ...);
+
+/* Returns allocator structure from data pointer */
+static vg_linear_allocator *vg_linear_header( void *data )
+{
+ vg_linear_allocator *ptr = data;
+ ptr --;
+
+ return ptr;
+}
+
+/* allocate something from a linear allocator */
+__attribute__((warn_unused_result))
+VG_STATIC void *vg_linear_alloc( void *buffer, u32 size )
+{
+ vg_linear_allocator *alloc = vg_linear_header( buffer );
+
+ if( (alloc->cur + size) > alloc->size )
+ {
+ vg_error( "%u + %u > %u\n", alloc->cur, size, alloc->size );
+ vg_fatal_exit_loop( "linear allocator overflow" );
+ }
+
+ if( alloc->flags & VG_MEMORY_SYSTEM )
+ if( (alloc->allocation_count + 1) > VG_MAX_ALLOCATIONS )
+ vg_fatal_exit_loop( "Max linear allocations reached" );
+
+ void *data;
+
+ if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) )
+ {
+ data = malloc( size );
+
+#ifdef VG_DEBUG_ALLOCATIONS
+ vg_info( "malloc: %p[%u]\n", data, size );
+#endif
+
+ vg_allocation_meta *meta = &alloc->alloc_table[ alloc->allocation_count ];
+ meta->type = k_allocation_type_block;
+ meta->data = data;
+ }
+ else
+ {
+ data = buffer + alloc->cur;
+ }
+
+ alloc->allocation_count ++;
+ alloc->last_alloc = data;
+ alloc->last_alloc_size = size;
+ alloc->cur += size;
+
+ return data;
+}
+
+
+/* resize latest block of memory from linear */
+__attribute__((warn_unused_result))
+VG_STATIC void *vg_linear_resize( void *buffer, void *data, u32 newsize )
+{
+ vg_linear_allocator *alloc = vg_linear_header( buffer );
+
+ if( alloc->last_alloc != data )
+ vg_fatal_exit_loop( "This block has been fixed!" );
+
+ if( (alloc->cur - alloc->last_alloc_size + newsize) > alloc->size )
+ vg_fatal_exit_loop( "Cannot resize, overflow" );
+
+ alloc->cur -= alloc->last_alloc_size;
+ alloc->cur += newsize;
+ alloc->last_alloc_size = newsize;
+
+ if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) )
+ {
+ data = realloc( data, newsize );
+ if( !data )
+ vg_fatal_exit_loop( "realloc failed" );
+
+ alloc->alloc_table[ alloc->allocation_count-1 ].data = data;
+ alloc->last_alloc = data;
+
+#ifdef VG_DEBUG_ALLOCATIONS
+ vg_info( "realloc: %p (->%u)\n", data, newsize );
+#endif
+ return data;
+ }
+ else
+ {
+ return data;
+ }
+}
+
+/* its possible to delete just the last item */
+VG_STATIC void vg_linear_del( void *buffer, void *data )
+{
+ vg_linear_allocator *alloc = vg_linear_header( buffer );
+
+ if( alloc->last_alloc != data )
+ vg_fatal_exit_loop( "This block has been fixed!" );
+
+ if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) )
+ {
+ vg_allocation_meta *meta = &alloc->alloc_table[alloc->allocation_count-1];
+ if( meta->type == k_allocation_type_linear )
+ vg_fatal_exit_loop( "Cannot free a linear allocator in this conext" );
+
+ free( data );
+ }
+
+ alloc->allocation_count --;
+ alloc->cur -= alloc->last_alloc_size;
+ alloc->last_alloc = NULL;
+ alloc->last_alloc_size = 0;
+}
+
+/* extend latest block of memory from linear */
+__attribute__((warn_unused_result))
+VG_STATIC void *vg_linear_extend( void *buffer, void *data, u32 extra )
+{
+ vg_linear_allocator *alloc = vg_linear_header( buffer );
+
+ if( alloc->last_alloc != data )
+ vg_fatal_exit_loop( "This block has been fixed!" );
+
+ u32 new_size = alloc->last_alloc_size + extra;
+ return vg_linear_resize( buffer, data, new_size );
+}
+
+/* get the current usage of allocator */
+VG_STATIC u32 vg_linear_get_cur( void *buffer )
+{
+ vg_linear_allocator *alloc = vg_linear_header( buffer );
+ return alloc->cur;
+}
+
+/* get the capacity of allocator. TODO, should return free space? */
+VG_STATIC u32 vg_linear_get_capacity( void *buffer )
+{
+ vg_linear_allocator *alloc = vg_linear_header( buffer );
+ return alloc->size;
+}
+
+/* yeet all memory from linear allocator */
+VG_STATIC void vg_linear_clear( void *buffer )
+{
+ vg_linear_allocator *alloc = vg_linear_header( buffer );
+
+#ifdef VG_DEBUG_ALLOCATIONS
+ if( alloc->flags & VG_MEMORY_SYSTEM )
+ vg_info( "linear_clear on %p\n", alloc );
+#endif
+
+ /* libc mode we recursively free any allocations made */
+ if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) )
+ {
+ for( u32 i=0; i<alloc->allocation_count; i++ )
+ {
+ vg_allocation_meta *meta = &alloc->alloc_table[i];
+
+ if( meta->type == k_allocation_type_block )
+ {
+ free( meta->data );
+
+#ifdef VG_DEBUG_ALLOCATIONS
+ vg_info( "free(%p) [%d]\n", meta->data, meta->type );
+#endif
+ }
+ else
+ {
+ vg_linear_clear( meta->data );
+ vg_linear_allocator *sub = vg_linear_header( meta->data );
+
+#ifdef VG_DEBUG_ALLOCATIONS
+ vg_info( "free(%p) [alloc_table]\n", sub->alloc_table );
+ vg_info( "free(%p) [%d]\n", sub, meta->type );
+#endif
+
+ free( sub->alloc_table );
+ free( sub );
+ }
+ }
+ }
+
+ alloc->last_alloc = NULL;
+ alloc->last_alloc_size = 0;
+ alloc->allocation_count = 0;
+ alloc->cur = 0;
+}
+
+/* allocate a FIXED SIZE linear allocator */
+VG_STATIC void *vg_create_linear_allocator( void *lin_alloc, u32 size,
+ u16 flags )
+{
+ assert( sizeof( vg_linear_allocator ) == 32 );
+
+ vg_linear_allocator *header;
+ u32 block_size = size + sizeof(vg_linear_allocator);
+
+ /* Creating it inside an existing one */
+ if( lin_alloc )
+ {
+ vg_linear_allocator *alloc = vg_linear_header( lin_alloc );
+
+ if( alloc->cur + block_size > alloc->size )
+ vg_fatal_exit_loop( "Out of memory" );
+
+ if( alloc->allocation_count + 1 > VG_MAX_ALLOCATIONS )
+ vg_fatal_exit_loop( "Max allocations in linear allocator" );
+
+ if( (flags && VG_MEMORY_SYSTEM) && (alloc->flags & VG_MEMORY_REALTIME) )
+ vg_fatal_exit_loop( "Cannot declare realtime allocator inside systems"
+ " allocator" );
+
+ if( vg_mem.use_libc_malloc )
+ {
+ vg_allocation_meta *meta =
+ &alloc->alloc_table[ alloc->allocation_count ];
+
+ if( flags & VG_MEMORY_REALTIME )
+ header = malloc( block_size );
+ else
+ header = malloc( sizeof(vg_linear_allocator) );
+
+#ifdef VG_DEBUG_ALLOCATIONS
+ vg_info( "linear_create(sub) malloc(%p)\n", header );
+#endif
+
+ meta->data = header+1;
+ meta->type = k_allocation_type_linear;
+ }
+ else
+ {
+ header = lin_alloc + alloc->cur;
+ }
+
+ alloc->cur += block_size;
+ alloc->last_alloc = NULL; /* cant resize this block! */
+ alloc->last_alloc_size = block_size;
+
+ alloc->allocation_count ++;
+ }
+ else
+ {
+ if( vg_mem.use_libc_malloc && (flags & VG_MEMORY_SYSTEM) )
+ header = malloc( sizeof(vg_linear_allocator) );
+ else
+ header = malloc( block_size );
+
+#ifdef VG_DEBUG_ALLOCATIONS
+ vg_info( "linear_create malloc(%p)\n", header );
+#endif
+ }
+
+ header->allocation_count = 0;
+ header->cur = 0;
+ header->last_alloc = NULL;
+ header->last_alloc_size = 0;
+ header->size = size;
+ header->flags = flags;
+
+ if( vg_mem.use_libc_malloc && (flags & VG_MEMORY_SYSTEM) )
+ {
+ u32 table_size = sizeof(vg_allocation_meta)*VG_MAX_ALLOCATIONS;
+ header->alloc_table = malloc( table_size );
+#ifdef VG_DEBUG_ALLOCATIONS
+ vg_info( "linear_create(%p) [alloc_table]\n", header->alloc_table );
+#endif
+ }
+ else
+ header->alloc_table = NULL;
+
+ return header+1;
+}
+
+/* request all the memory we need in advance */
+VG_STATIC void vg_prealloc_quota( u32 size )
+{
+ u32 size_scratch = 10*1024*1024;
+ size = VG_MAX( size, size_scratch );
+
+ vg_mem.rtmemory = vg_create_linear_allocator( NULL, size, VG_MEMORY_SYSTEM );
+ vg_mem.scratch = vg_create_linear_allocator( vg_mem.rtmemory,
+ size_scratch,
+ VG_MEMORY_SYSTEM );
+}
+
+#endif /* VG_MEM_H */
+
+#if 0
+
+#ifndef VG_MEM_H
+#define VG_MEM_H
+
+#include "vg_stdint.h"
+#include "vg_platform.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+
typedef struct vg_linear_allocator vg_linear_allocator;
struct
* TODO: Fallback on libc
*/
+//#define VG_USE_MALLOC
+
VG_STATIC void vg_error(const char *fmt, ...);
/* allocate something from a linear allocator */
vg_fatal_exit_loop( "Linear allocator out of memory" );
}
+#ifdef VG_USE_MALLOC
+ void *data = malloc(size);
+#else
void *data = allocator + allocptr->cur;
+#endif
+
allocptr->cur += size;
- allocptr->last_alloc = data;
allocptr->last_alloc_size = size;
+ allocptr->last_alloc = data;
return data;
}
if( allocptr->last_alloc == data )
{
allocptr->cur -= allocptr->last_alloc_size;
+
+#ifdef VG_USE_MALLOC
+ allocptr->cur += newsize;
+ void *newdata = realloc( data, newsize );
+ allocptr->last_alloc = newdata;
+ allocptr->last_alloc_size = newsize;
+
+ return newdata;
+#else
return vg_linear_alloc( allocator, newsize );
+#endif
}
else
{
+ vg_error( "%p != %p\n", allocptr->last_alloc, data );
vg_fatal_exit_loop( "Cannot resize this buffer anymore" );
}
VG_STATIC void vg_linear_del( void *allocator, void *data )
{
+#ifdef VG_USE_MALLOC
+ free(data);
+#else
void *ignore = vg_linear_resize( allocator, data, 0 );
+#endif
vg_linear_allocator *allocptr = allocator;
allocptr --;
return allocptr->size;
}
+#if 0
/* get the size of the last allocated thing */
VG_STATIC u32 vg_linear_last_size( void *allocator )
{
return allocptr->last_alloc_size;
}
+#endif
/* yeet all memory from linear allocator */
VG_STATIC void vg_linear_clear( void *allocator )
}
#endif /* VG_MEM_H */
+
+#endif