From 35564cceef6bd50652dff38c0a6212129061fe36 Mon Sep 17 00:00:00 2001 From: jacob Date: Wed, 30 Jul 2025 21:05:23 -0500 Subject: [PATCH] sound layer refactor --- src/app/app_core.c | 2 +- src/font/font_core.h | 5 +- src/mixer/mixer_core.c | 2 +- src/sound/sound_core.c | 139 +++++++++++++++++++---------------------- src/sound/sound_core.h | 70 ++++++++++++++++++--- 5 files changed, 130 insertions(+), 88 deletions(-) diff --git a/src/app/app_core.c b/src/app/app_core.c index 9262bed8..2c5147f4 100644 --- a/src/app/app_core.c +++ b/src/app/app_core.c @@ -243,7 +243,7 @@ void P_AppStartup(String args_str) F_StartupReceipt font_sr = F_Startup(&asset_cache_sr, &ttf_sr); S_StartupReceipt sprite_sr = sprite_startup(); M_StartupReceipt mixer_sr = M_Startup(); - SND_StartupReceipt sound_sr = sound_startup(&asset_cache_sr); + SND_StartupReceipt sound_sr = SND_Startup(&asset_cache_sr); D_StartupReceipt draw_sr = D_Startup(&font_sr); SimStartupReceipt sim_sr = sim_startup(); diff --git a/src/font/font_core.h b/src/font/font_core.h index f42cde34..1c631e82 100644 --- a/src/font/font_core.h +++ b/src/font/font_core.h @@ -40,9 +40,8 @@ Struct(F_LoadJobSigStore) P_Mutex mutex; }; -/* ========================== * - * Global state - * ========================== */ +//////////////////////////////// +//~ Shared state #define F_LookupTableSize (256) diff --git a/src/mixer/mixer_core.c b/src/mixer/mixer_core.c index f64c7309..ae2e50f4 100644 --- a/src/mixer/mixer_core.c +++ b/src/mixer/mixer_core.c @@ -295,7 +295,7 @@ M_PcmF32 M_MixAllTracks(Arena *arena, u64 frame_count) SND_Sound *source = mix->source; M_TrackDesc desc = mix->desc; M_EffectData *effect_data = &mix->effect_data; - b32 source_is_stereo = source->flags & SOUND_FLAG_STEREO; + b32 source_is_stereo = source->flags & SND_SoundFlag_Stereo; f32 speed = MaxF32(0, desc.speed); //- Determine sample range diff --git a/src/sound/sound_core.c b/src/sound/sound_core.c index f0100ddc..fb1c51b6 100644 --- a/src/sound/sound_core.c +++ b/src/sound/sound_core.c @@ -1,76 +1,56 @@ -#define SOUND_SAMPLE_RATE 48000 +SND_SharedState SND_shared_state = ZI; -struct sound_task_params { - struct sound_task_params *next_free; +//////////////////////////////// +//~ Startup - u32 flags; - AC_Asset *asset; - u64 path_len; - char path_cstr[1024]; -}; - -struct sound_task_params_store { - struct sound_task_params *head_free; - Arena *arena; - P_Mutex mutex; -}; - -/* ========================== * - * Global state - * ========================== */ - -Global struct { - struct sound_task_params_store params; -} G = ZI, DebugAlias(G, G_sound); - -/* ========================== * - * Startup - * ========================== */ - -SND_StartupReceipt sound_startup(AC_StartupReceipt *asset_cache_sr) +SND_StartupReceipt SND_Startup(AC_StartupReceipt *asset_cache_sr) { __prof; + SND_SharedState *g = &SND_shared_state; (UNUSED)asset_cache_sr; - G.params.arena = AllocArena(Gibi(64)); + g->params.arena = AllocArena(Gibi(64)); return (SND_StartupReceipt) { 0 }; } -/* ========================== * - * Load task param store - * ========================== */ +//////////////////////////////// +//~ Job sig store -internal struct sound_task_params *sound_task_params_alloc(void) +SND_LoadAssetJobSig *SND_AllocJobSig(void) { - struct sound_task_params *p = 0; + SND_SharedState *g = &SND_shared_state; + SND_LoadAssetJobSig *p = 0; { - P_Lock lock = P_LockE(&G.params.mutex); - if (G.params.head_free) { - p = G.params.head_free; - G.params.head_free = p->next_free; - } else { - p = PushStruct(G.params.arena, struct sound_task_params); + P_Lock lock = P_LockE(&g->params.mutex); + if (g->params.head_free) + { + p = g->params.head_free; + g->params.head_free = p->next_free; + } + else + { + p = PushStruct(g->params.arena, SND_LoadAssetJobSig); } P_Unlock(&lock); } return p; } -internal void sound_task_params_release(struct sound_task_params *p) +void SND_ReleaseJobSig(SND_LoadAssetJobSig *p) { - P_Lock lock = P_LockE(&G.params.mutex); - p->next_free = G.params.head_free; - G.params.head_free = p; + SND_SharedState *g = &SND_shared_state; + P_Lock lock = P_LockE(&g->params.mutex); + p->next_free = g->params.head_free; + g->params.head_free = p; P_Unlock(&lock); } -/* ========================== * - * Load - * ========================== */ +//////////////////////////////// +//~ Load job -internal P_JobDef(sound_load_asset_job, job) +P_JobDef(SND_LoadAssetJob, job) { __prof; - struct sound_task_params *params = job.sig; + SND_LoadAssetJobSig *params = job.sig; TempArena scratch = BeginScratchNoConflict(); String path = STRING(params->path_len, (u8 *)params->path_cstr); AC_Asset *asset = params->asset; @@ -87,22 +67,28 @@ internal P_JobDef(sound_load_asset_job, job) MP3_Result decoded = ZI; { R_Resource sound_rs = R_OpenResource(path); - if (R_ResourceExists(&sound_rs)) { + if (R_ResourceExists(&sound_rs)) + { u64 decode_flags = 0; - if (flags & SOUND_FLAG_STEREO) { + if (flags & SND_SoundFlag_Stereo) + { decode_flags |= MP3_DecodeFlag_Stereo; } - decoded = MP3_Decode(scratch.arena, R_GetResourceData(&sound_rs), SOUND_SAMPLE_RATE, decode_flags); - if (!decoded.success) { + decoded = MP3_Decode(scratch.arena, R_GetResourceData(&sound_rs), SND_SampleRate, decode_flags); + if (!decoded.success) + { error_msg = Lit("Failed to decode sound file"); } - } else { + } + else + { error_msg = Lit("Resource not found"); } R_CloseResource(&sound_rs); } - if (decoded.success) { + if (decoded.success) + { /* Store */ SND_Sound *sound = 0; u64 samples_count = decoded.samples_count; @@ -123,7 +109,9 @@ internal P_JobDef(sound_load_asset_job, job) P_LogSuccessF("Loaded sound \"%F\" in %F seconds", FmtString(path), FmtFloat(SecondsFromNs(P_TimeNs() - start_ns))); AC_MarkReady(asset, sound); - } else { + } + else + { P_LogErrorF("Error loading sound \"%F\": %F", FmtString(path), FmtString(error_msg)); /* Store */ @@ -137,32 +125,37 @@ internal P_JobDef(sound_load_asset_job, job) AC_MarkReady(asset, sound); } - sound_task_params_release(params); + SND_ReleaseJobSig(params); EndScratch(scratch); } -AC_Asset *sound_load_asset(String path, u32 flags, b32 wait) +//////////////////////////////// +//~ Load sound + +AC_Asset *SND_LoadAsset(String path, u32 flags, b32 wait) { __prof; TempArena scratch = BeginScratchNoConflict(); /* Generate and append sound flags to path key */ String key = StringFormat(scratch.arena, - Lit("%F%F_sound"), - FmtString(path), - FmtUint((u64)flags)); + Lit("%F%F_sound"), + FmtString(path), + FmtUint((u64)flags)); u64 hash = AC_HashFromKey(key); b32 is_first_touch; AC_Asset *asset = AC_TouchCache(key, hash, &is_first_touch); - if (is_first_touch) { + if (is_first_touch) + { /* Assemble task params */ - struct sound_task_params *params = sound_task_params_alloc(); - if (path.len > (sizeof(params->path_cstr) - 1)) { + SND_LoadAssetJobSig *params = SND_AllocJobSig(); + if (path.len > (sizeof(params->path_cstr) - 1)) + { P_Panic(StringFormat(scratch.arena, - Lit("Sound path \"%F\" too long!"), - FmtString(path))); + Lit("Sound path \"%F\" too long!"), + FmtString(path))); } CstrBuffFromStringToBuff(StringFromArray(params->path_cstr), path); params->path_len = path.len; @@ -171,8 +164,9 @@ AC_Asset *sound_load_asset(String path, u32 flags, b32 wait) /* PushStruct task */ AC_MarkLoading(asset); - P_Run(1, sound_load_asset_job, params, P_Pool_Background, P_Priority_Low, &asset->counter); - if (wait) { + P_Run(1, SND_LoadAssetJob, params, P_Pool_Background, P_Priority_Low, &asset->counter); + if (wait) + { AC_WaitOnAssetReady(asset); } } @@ -181,19 +175,18 @@ AC_Asset *sound_load_asset(String path, u32 flags, b32 wait) return asset; } -SND_Sound *sound_load_async(String path, u32 flags) +SND_Sound *SND_LoadSoundAsync(String path, u32 flags) { __prof; - AC_Asset *asset = sound_load_asset(path, flags, 0); + AC_Asset *asset = SND_LoadAsset(path, flags, 0); SND_Sound *sound = (SND_Sound *)AC_DataFromStore(asset); return sound; } - -SND_Sound *sound_load(String path, u32 flags) +SND_Sound *SND_LoadSoundWait(String path, u32 flags) { __prof; - AC_Asset *asset = sound_load_asset(path, flags, 1); + AC_Asset *asset = SND_LoadAsset(path, flags, 1); AC_WaitOnAssetReady(asset); SND_Sound *sound = (SND_Sound *)AC_DataFromStore(asset); return sound; diff --git a/src/sound/sound_core.h b/src/sound/sound_core.h index 53a3e659..1e0561ab 100644 --- a/src/sound/sound_core.h +++ b/src/sound/sound_core.h @@ -1,17 +1,67 @@ -#define SOUND_FLAG_NONE 0x0 -#define SOUND_FLAG_STEREO 0x1 +//////////////////////////////// +//~ Sound structs -typedef struct SND_Sound SND_Sound; -struct SND_Sound { +#define SND_SampleRate 48000 + +typedef u32 SND_SoundFlag; enum +{ + SND_SoundFlag_None = 0, + SND_SoundFlag_Stereo = (1 << 0) +}; + +Struct(SND_Sound) +{ u32 flags; u64 samples_count; i16 *samples; }; -typedef struct SND_StartupReceipt SND_StartupReceipt; -struct SND_StartupReceipt { i32 _; }; -SND_StartupReceipt sound_startup(AC_StartupReceipt *asset_cache_sr); +//////////////////////////////// +//~ Sound job types -AC_Asset *sound_load_asset(String path, u32 flags, b32 wait); -SND_Sound *sound_load_async(String path, u32 flags); -SND_Sound *sound_load(String path, u32 flags); +Struct(SND_LoadAssetJobSig) +{ + SND_LoadAssetJobSig *next_free; + + u32 flags; + AC_Asset *asset; + u64 path_len; + char path_cstr[1024]; +}; + +Struct(SND_LoadAssetJobSigStore) +{ + SND_LoadAssetJobSig *head_free; + Arena *arena; + P_Mutex mutex; +}; + +//////////////////////////////// +//~ Shared state + +Struct(SND_SharedState) +{ + SND_LoadAssetJobSigStore params; +}; + +extern SND_SharedState SND_shared_state; + +//////////////////////////////// +//~ Startup + +Struct(SND_StartupReceipt) { i32 _; }; +SND_StartupReceipt SND_Startup(AC_StartupReceipt *asset_cache_sr); + +//////////////////////////////// +//~ Sound load job + +SND_LoadAssetJobSig *SND_AllocJobSig(void); +void SND_ReleaseJobSig(SND_LoadAssetJobSig *p); + +//////////////////////////////// +//~ Sound load operations + +P_JobDef(SND_LoadAssetJob, job); +AC_Asset *SND_LoadAsset(String path, u32 flags, b32 wait); +SND_Sound *SND_LoadSoundAsync(String path, u32 flags); +SND_Sound *SND_LoadSoundWait(String path, u32 flags);