From 3e0c4b531435eb1a0b04653721d65285488b1487 Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Sun, 11 Apr 2021 20:03:21 +0200 Subject: [PATCH] Stream music files from disk with FMOD, instead of preloading the entire file into memory and playing from there. Added a helper function to COM_ to assist with this. This removes the noticeable delay when loading into a level, and simplifies the music playback code as well. --- engine/Quake/bgmusic.c | 32 +++++--------------------------- engine/Quake/common.c | 28 ++++++++++++++++++++++++---- engine/Quake/common.h | 1 + 3 files changed, 30 insertions(+), 31 deletions(-) diff --git a/engine/Quake/bgmusic.c b/engine/Quake/bgmusic.c index 8a9f9c6..f1f1306 100644 --- a/engine/Quake/bgmusic.c +++ b/engine/Quake/bgmusic.c @@ -42,7 +42,6 @@ extern FMOD_SYSTEM *fmod_system; FMOD_CHANNELGROUP *bgm_channelGroup = NULL; FMOD_CHANNEL *bgm_channel = NULL; FMOD_SOUND *bgm_sound = NULL; -byte *bgm_data = NULL; static const char *extensions[] = { @@ -136,9 +135,7 @@ void BGM_Shutdown (void) static qboolean BGM_PlayStream(const char *filename) { - FILE *f; - int len; - FMOD_CREATESOUNDEXINFO exinfo; + char netpath[MAX_OSPATH]; FMOD_RESULT result; if (!fmod_system || !bgm_channelGroup) @@ -147,28 +144,13 @@ static qboolean BGM_PlayStream(const char *filename) return false; } - len = COM_FOpenFile(filename, &f, NULL); - fclose(f); - if (len < 1) + if (!COM_FullFilePath(filename, netpath, sizeof(netpath))) { Con_Printf("Could not open BGM file %s, file not found\n", filename); return false; } - bgm_data = COM_LoadMallocFile(filename, NULL); // TODO is there really no better way to pre-cache this data than with malloc? - if (!bgm_data) - { - Con_Printf("Failed to load BGM file %s\n", filename); - return false; - } - - Con_DPrintf("BGM_PlayStream: Successfully loaded %s\n", filename); - - memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO)); - exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO); - exinfo.length = len; - - result = FMOD_System_CreateSound(fmod_system, (const char*)bgm_data, FMOD_OPENMEMORY | FMOD_2D, &exinfo, &bgm_sound); + result = FMOD_System_CreateSound(fmod_system, netpath, FMOD_CREATESTREAM | FMOD_2D, NULL, &bgm_sound); if (result != FMOD_OK || !bgm_sound) { Con_Printf("Failed to create FMOD sound: %s\n", FMOD_ErrorString(result)); @@ -176,6 +158,8 @@ static qboolean BGM_PlayStream(const char *filename) return false; } + Con_DPrintf("BGM_PlayStream: Successfully loaded %s\n", filename); + result = FMOD_System_PlaySound(fmod_system, bgm_sound, bgm_channelGroup, false, &bgm_channel); if (result != FMOD_OK || !bgm_channel) { @@ -298,12 +282,6 @@ void BGM_Stop(void) FMOD_Sound_Release(bgm_sound); bgm_sound = NULL; } - - if (bgm_data) - { - free(bgm_data); - bgm_data = NULL; - } } void BGM_Pause (void) diff --git a/engine/Quake/common.c b/engine/Quake/common.c index a449001..313f7b0 100644 --- a/engine/Quake/common.c +++ b/engine/Quake/common.c @@ -1604,11 +1604,9 @@ If neither of file or handle is set, this can be used for detecting a file's presence. =========== */ -static int COM_FindFile (const char *filename, int *handle, FILE **file, - unsigned int *path_id) +static int COM_FindFile2(const char *filename, int *handle, FILE **file, unsigned int *path_id, char *netpath, size_t size) { searchpath_t *search; - char netpath[MAX_OSPATH]; pack_t *pak; int i, findtime; @@ -1616,6 +1614,7 @@ static int COM_FindFile (const char *filename, int *handle, FILE **file, Sys_Error ("COM_FindFile: both handle and file set"); file_from_pak = 0; + memset(netpath, 0, size); // // search through the path, one element at a time @@ -1661,7 +1660,7 @@ static int COM_FindFile (const char *filename, int *handle, FILE **file, continue; } - q_snprintf (netpath, sizeof(netpath), "%s/%s",search->filename, filename); + q_snprintf (netpath, size, "%s/%s",search->filename, filename); findtime = Sys_FileTime (netpath); if (findtime == -1) continue; @@ -1703,6 +1702,11 @@ static int COM_FindFile (const char *filename, int *handle, FILE **file, return com_filesize; } +static int COM_FindFile(const char *filename, int *handle, FILE **file, unsigned int *path_id) +{ + char netpath[MAX_OSPATH]; + return COM_FindFile2(filename, handle, file, path_id, netpath, sizeof(netpath)); +} /* =========== @@ -1762,6 +1766,22 @@ void COM_CloseFile (int h) Sys_FileClose (h); } +/* +================ +COM_FullFilePath + +Get the full canonical file path of the requested file on disk. +If it is inside a pak file, this returns false. +================ +*/ +qboolean COM_FullFilePath(const char *filename, char *netpath, size_t size) +{ + int ret = COM_FindFile2(filename, NULL, NULL, NULL, netpath, size); + if (ret < 0 || !*netpath || file_from_pak) + return false; + + return true; +} /* ============ diff --git a/engine/Quake/common.h b/engine/Quake/common.h index eff6b64..b7b9afb 100644 --- a/engine/Quake/common.h +++ b/engine/Quake/common.h @@ -233,6 +233,7 @@ int COM_OpenFile (const char *filename, int *handle, unsigned int *path_id); int COM_FOpenFile (const char *filename, FILE **file, unsigned int *path_id); qboolean COM_FileExists (const char *filename, unsigned int *path_id); void COM_CloseFile (int h); +qboolean COM_FullFilePath(const char *filename, char *netpath, size_t size); // these procedures open a file using COM_FindFile and loads it into a proper // buffer. the buffer is allocated with a total size of com_filesize + 1. the