diff --git a/engine/Quake/q_sound.h b/engine/Quake/q_sound.h index ca7a385..f9f5018 100644 --- a/engine/Quake/q_sound.h +++ b/engine/Quake/q_sound.h @@ -42,7 +42,9 @@ typedef struct sfx_s cache_user_t cache; #if USE_FMOD FMOD_SOUND *sound; - unsigned int samples; + unsigned int length; // milliseconds + int loopstart; + int loopend; #endif } sfx_t; diff --git a/engine/Quake/snd_fmod.c b/engine/Quake/snd_fmod.c index 64b2267..36bd089 100644 --- a/engine/Quake/snd_fmod.c +++ b/engine/Quake/snd_fmod.c @@ -152,13 +152,13 @@ static unsigned int SND_GetDelay(const sfx_t *sfx, float maxseconds) { unsigned int delay; - delay = maxseconds * fmod_samplerate; - if (delay > sfx->samples) - delay = sfx->samples; + delay = maxseconds * 1000; + if (delay > sfx->length) + delay = sfx->length; if (delay > 0) delay = rand() % delay; - return delay; + return delay * fmod_samplerate / 1000; } /* @@ -285,8 +285,17 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f FMOD_VectorCopy(origin, position); FMOD_Channel_Set3DAttributes(channel, &position, NULL); - FMOD_Channel_SetMode(channel, FMOD_LOOP_OFF); // TODO: some entity sounds do need to loop, e.g. moving elevators. How is this done? FMOD_Channel_SetVolume(channel, fvol); + + if (sfx->loopstart >= 0) + { + FMOD_Channel_SetMode(channel, FMOD_LOOP_NORMAL); + FMOD_Channel_SetLoopPoints(channel, sfx->loopstart, FMOD_TIMEUNIT_MS, sfx->loopend, FMOD_TIMEUNIT_MS); + } + else + { + FMOD_Channel_SetMode(channel, FMOD_LOOP_OFF); + } // Anything coming from the view entity will always be full volume, and entchannel -1 is used for local sounds (e.g. menu sounds) if (entchannel < 0 || entnum == cl.viewentity) @@ -442,13 +451,13 @@ sfxcache_t *S_LoadSound(sfx_t *s) { char namebuffer[256]; byte *data; - int len, h; + wavinfo_t info; FMOD_CREATESOUNDEXINFO exinfo; FMOD_RESULT result; #if _DEBUG FMOD_SOUND_TYPE type; FMOD_SOUND_FORMAT format; - int channels, bits, loopcount; + int channels, bits; #endif if (!fmod_system) @@ -461,11 +470,6 @@ sfxcache_t *S_LoadSound(sfx_t *s) 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) { @@ -473,9 +477,16 @@ sfxcache_t *S_LoadSound(sfx_t *s) return NULL; } + info = GetWavinfo(s->name, data, com_filesize); + if (!info.channels) + { + Con_Printf("Invalid WAV file: %s\n", namebuffer); + return NULL; + } + memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO)); exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO); - exinfo.length = len; + exinfo.length = com_filesize; result = FMOD_System_CreateSound(fmod_system, (const char*)data, FMOD_3D | FMOD_OPENMEMORY, &exinfo, &s->sound); if (result != FMOD_OK) @@ -484,12 +495,21 @@ sfxcache_t *S_LoadSound(sfx_t *s) return NULL; } - FMOD_Sound_GetLength(s->sound, &s->samples, FMOD_TIMEUNIT_PCM); + // Collect data required for looping and delay + if (info.loopstart >= 0) + { + s->loopstart = info.loopstart * 1000 / info.rate; + s->loopend = info.samples * 1000 / info.rate; + } + else + { + s->loopstart = s->loopend = -1; + } + FMOD_Sound_GetLength(s->sound, &s->length, FMOD_TIMEUNIT_MS); #if _DEBUG FMOD_Sound_GetFormat(s->sound, &type, &format, &channels, &bits); - FMOD_Sound_GetLoopCount(s->sound, &loopcount); - Con_DPrintf("[FMOD] Loaded sound '%s': type %d, format %d, %d channel(s), %d bits, %d samples, loopcount = %d\n", s->name, type, format, channels, bits, s->samples, loopcount); + Con_DPrintf("[FMOD] Loaded sound '%s': type %d, format %d, %d channel(s), %d bits, %d ms, %d samples, loopstart = %d\n", s->name, type, format, channels, bits, s->length, info.samples, s->loopstart); #endif return NULL; // Return value is unused; FMOD has its own internal cache, we never need to use Quake's sfxcache_t diff --git a/engine/Quake/snd_mem.c b/engine/Quake/snd_mem.c index e46c76c..e444d21 100644 --- a/engine/Quake/snd_mem.c +++ b/engine/Quake/snd_mem.c @@ -162,7 +162,7 @@ sfxcache_t *S_LoadSound (sfx_t *s) return sc; } - +#endif // USE_FMOD /* =============================================================================== @@ -352,4 +352,3 @@ wavinfo_t GetWavinfo (const char *name, byte *wav, int wavlength) return info; } -#endif // USE_FMOD