Browse Source

Implemented more FMOD goodness:

- Initialization of FMOD System (if necessary), diagnostics and setup of SFX channel group
- Loading of FMOD sounds from either disk or PAK file
console
Nico de Poel 5 years ago
parent
commit
68db1e78ae
  1. 7
      engine/Quake/q_sound.h
  2. 9
      engine/Quake/snd_dma.c
  3. 173
      engine/Quake/snd_fmod.c

7
engine/Quake/q_sound.h

@ -25,6 +25,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef __QUAKE_SOUND__
#define __QUAKE_SOUND__
#if USE_FMOD
#include "fmod.h"
#endif
/* !!! if this is changed, it must be changed in asm_i386.h too !!! */
typedef struct
{
@ -36,6 +40,9 @@ typedef struct sfx_s
{
char name[MAX_QPATH];
cache_user_t cache;
#if USE_FMOD
FMOD_SOUND *sound;
#endif
} sfx_t;
/* !!! if this is changed, it must be changed in asm_i386.h too !!! */

9
engine/Quake/snd_dma.c

@ -70,7 +70,7 @@ static int num_sfx;
static sfx_t *ambient_sfx[NUM_AMBIENTS];
static qboolean sound_started = false;
qboolean sound_started = false;
static qboolean snd_initialized = false;
cvar_t bgmvolume = {"bgmvolume", "1", CVAR_ARCHIVE};
@ -266,6 +266,7 @@ void S_Shutdown (void)
shm = NULL;
}
#endif // USE_FMOD
// =======================================================================
// Load a sound
@ -277,7 +278,7 @@ S_FindName
==================
*/
static sfx_t *S_FindName (const char *name)
sfx_t *S_FindName (const char *name)
{
int i;
sfx_t *sfx;
@ -308,6 +309,7 @@ static sfx_t *S_FindName (const char *name)
return sfx;
}
#ifndef USE_FMOD
/*
==================
@ -326,6 +328,8 @@ void S_TouchSound (const char *name)
Cache_Check (&sfx->cache);
}
#endif // USE_FMOD
/*
==================
S_PrecacheSound
@ -348,6 +352,7 @@ sfx_t *S_PrecacheSound (const char *name)
return sfx;
}
#ifndef USE_FMOD
//=============================================================================

173
engine/Quake/snd_fmod.c

@ -4,34 +4,86 @@
#include "fmod.h"
#include "fmod_errors.h"
extern qboolean sound_started; // in snd_dma.c
FMOD_SYSTEM *fmod_system = NULL;
static qboolean fmod_ownership = false;
static FMOD_CHANNELGROUP *sfx_channelGroup = NULL;
#if 1
//void S_Init(void)
//{
// // Register cvars (see snd_dma.c) and check parameters
// // Call S_Startup
// // Call S_StopAllSounds(true)
//
// // Note: could actually keep the original S_Init from snd_dma.c and have it call the above functions in here
//}
static const char *FMOD_SpeakerModeString(FMOD_SPEAKERMODE speakermode);
void S_Startup(void)
{
FMOD_RESULT result;
FMOD_SPEAKERMODE speakermode;
unsigned int version;
int driver, systemrate, numchannels;
char name[1024];
// Create FMOD System if it doesn't exist already
// Create SFX channel group
if (!fmod_system)
{
result = FMOD_System_Create(&fmod_system);
if (result != FMOD_OK)
{
Con_Printf("Failed to create FMOD System: %s\n", FMOD_ErrorString(result));
return;
}
fmod_ownership = true;
}
result = FMOD_System_GetVersion(fmod_system, &version);
if (result != FMOD_OK)
{
Con_Printf("Failed to retrieve FMOD version: %s\n", FMOD_ErrorString(result));
return;
}
result = FMOD_System_GetDriver(fmod_system, &driver);
if (result != FMOD_OK)
{
Con_Printf("Failed to retrieve selected FMOD driver: %s\n", FMOD_ErrorString(result));
return;
}
result = FMOD_System_GetDriverInfo(fmod_system, driver, name, sizeof(name), NULL, &systemrate, &speakermode, &numchannels);
if (result != FMOD_OK)
{
Con_Printf("Failed to retrieve FMOD driver info: %s\n", FMOD_ErrorString(result));
return;
}
Con_Printf("FMOD version %01x.%02x.%02x, driver '%s', %s speaker mode, %d Hz, %d channels\n",
(version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff, name, FMOD_SpeakerModeString(speakermode), systemrate, numchannels);
result = FMOD_System_CreateChannelGroup(fmod_system, "SFX", &sfx_channelGroup);
if (result != FMOD_OK)
{
Con_Printf("Failed to create FMOD SFX channel group: %s\n", FMOD_ErrorString(result));
return;
}
// Could use System::set3DRolloffCallback to set up a (attenuation / sound_nominal_clip_dist) distance multiplier (would need to use ChannelControl::setUserData to hold ref to attn value)
// Note: sound_nominal_clip_dist could be dynamic to allow a small sound 'bubble' for local multiplayer
// Set sound_started to true
Con_DPrintf("[FMOD] Startup\n");
sound_started = true;
}
void S_Shutdown(void)
{
// Destroy SFX channel group
// If we created FMOD System (and consequently own it), destroy it here
Con_DPrintf("[FMOD] Shutdown\n");
// Destroy any SFX channels still in use
// If we created the FMOD System (and consequently own it), destroy it here
if (fmod_ownership)
{
FMOD_System_Close(fmod_system);
fmod_system = NULL;
fmod_ownership = false;
}
}
void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation)
@ -50,10 +102,6 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f
// ChannelControl::setPaused = false
// Store channel handle at position entchannel
if (sfx)
Con_DPrintf("[FMOD] Start sound %s for entity %d channel %d\n", sfx->name, entnum, entchannel);
else
Con_DPrintf("[FMOD] Start sound NULL for entity %d channel %d\n", entnum, entchannel);
}
void S_StaticSound(sfx_t *sfx, vec3_t origin, float vol, float attenuation)
@ -61,15 +109,11 @@ void S_StaticSound(sfx_t *sfx, vec3_t origin, float vol, float attenuation)
// Similar to above, but without the per-entity channel group song and dance
// Check if sound is looped (should be) and FMOD_Channel_SetMode to looped
// Set Channel::setLoopPoints if the sfxcache specifies something non-standard
if (sfx)
Con_DPrintf("[FMOD] Static sound: %s\n", sfx->name);
else
Con_DPrintf("[FMOD] Static sound: NULL\n");
}
void S_StopSound(int entnum, int entchannel)
{
Con_DPrintf("[FMOD] Stop sound for entity %d channel %d\n", entnum, entchannel);
}
void S_StopAllSounds(qboolean clear)
@ -115,18 +159,91 @@ void S_UnblockSound(void)
S_SetMasterMute(0);
}
sfx_t *S_PrecacheSound(const char *sample)
sfxcache_t *S_LoadSound(sfx_t *s)
{
char namebuffer[256];
byte *data;
int len, h;
FMOD_CREATESOUNDEXINFO exinfo;
FMOD_RESULT result;
#if _DEBUG
FMOD_SOUND_TYPE type;
FMOD_SOUND_FORMAT format;
int channels, bits, loopcount;
unsigned int length;
#endif
if (!fmod_system)
return NULL;
// Check if it's already loaded
if (s->sound)
return NULL;
q_strlcpy(namebuffer, "sound/", sizeof(namebuffer));
q_strlcat(namebuffer, s->name, sizeof(namebuffer));
// We need to briefly open the file to figure out its length, which FMOD needs to know
len = COM_OpenFile(namebuffer, &h, NULL);
if (h >= 0)
COM_CloseFile(h);
data = COM_LoadHunkFile(namebuffer, NULL);
if (!data)
{
Con_Printf("Couldn't load %s\n", namebuffer);
return NULL;
}
memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));
exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
exinfo.length = len;
// System::createSound with FMOD_3D (sfx_t will need a pointer to FMOD_Sound)
// Might need to set rate and width? FMOD can probably figure this out by itself based on the WAV file contents
Con_DPrintf("[FMOD] Precaching sound: %s\n", sample);
return NULL;
// Might need to set rate and width? FMOD can probably figure this out by itself based on the WAV file contents
result = FMOD_System_CreateSound(fmod_system, (const char*)data, FMOD_3D | FMOD_OPENMEMORY, &exinfo, &s->sound);
if (result != FMOD_OK)
{
Con_Printf("Failed to create FMOD sound: %s\n", FMOD_ErrorString(result));
return NULL;
}
#if _DEBUG
FMOD_Sound_GetFormat(s->sound, &type, &format, &channels, &bits);
FMOD_Sound_GetLength(s->sound, &length, FMOD_TIMEUNIT_MS);
FMOD_Sound_GetLoopCount(s->sound, &loopcount);
Con_DPrintf("[FMOD] Loaded sound '%s': type %d, format %d, %d channel(s), %d bits, %d ms, loopcount = %d\n", s->name, type, format, channels, bits, length, loopcount);
#endif
return NULL; // Return value is unused; FMOD has its own internal cache, we never need to use Quake's sfxcache_t
}
void S_TouchSound(const char *sample)
{
}
#endif
static const char *FMOD_SpeakerModeString(FMOD_SPEAKERMODE speakermode)
{
switch (speakermode)
{
case FMOD_SPEAKERMODE_MONO:
return "Mono";
case FMOD_SPEAKERMODE_STEREO:
return "Stereo";
case FMOD_SPEAKERMODE_QUAD:
return "4.0 Quad";
case FMOD_SPEAKERMODE_SURROUND:
return "5.0 Surround";
case FMOD_SPEAKERMODE_5POINT1:
return "5.1 Surround";
case FMOD_SPEAKERMODE_7POINT1:
return "7.1 Surround";
case FMOD_SPEAKERMODE_7POINT1POINT4:
return "7.1.4 Surround";
default:
return "Unknown";
}
}
#endif // USE_FMOD
Loading…
Cancel
Save