|
|
@ -26,54 +26,29 @@ |
|
|
#include "snd_codec.h" |
|
|
#include "snd_codec.h" |
|
|
#include "bgmusic.h" |
|
|
#include "bgmusic.h" |
|
|
|
|
|
|
|
|
|
|
|
#if USE_FMOD |
|
|
|
|
|
#include "fmod.h" |
|
|
|
|
|
#include "fmod_errors.h" |
|
|
|
|
|
|
|
|
#define MUSIC_DIRNAME "music" |
|
|
#define MUSIC_DIRNAME "music" |
|
|
|
|
|
|
|
|
qboolean bgmloop; |
|
|
qboolean bgmloop; |
|
|
cvar_t bgm_extmusic = {"bgm_extmusic", "1", CVAR_ARCHIVE}; |
|
|
cvar_t bgm_extmusic = {"bgm_extmusic", "1", CVAR_ARCHIVE}; |
|
|
|
|
|
|
|
|
static qboolean no_extmusic= false; |
|
|
|
|
|
|
|
|
static qboolean no_extmusic = false; |
|
|
static float old_volume = -1.0f; |
|
|
static float old_volume = -1.0f; |
|
|
|
|
|
|
|
|
typedef enum _bgm_player |
|
|
|
|
|
{ |
|
|
|
|
|
BGM_NONE = -1, |
|
|
|
|
|
BGM_MIDIDRV = 1, |
|
|
|
|
|
BGM_STREAMER |
|
|
|
|
|
} bgm_player_t; |
|
|
|
|
|
|
|
|
extern FMOD_SYSTEM *fmod_system; |
|
|
|
|
|
FMOD_CHANNELGROUP *bgm_channelGroup; |
|
|
|
|
|
FMOD_CHANNEL *bgm_channel; |
|
|
|
|
|
FMOD_SOUND *bgm_sound; |
|
|
|
|
|
byte *bgm_data; |
|
|
|
|
|
|
|
|
typedef struct music_handler_s |
|
|
|
|
|
|
|
|
static const char *extensions[] = |
|
|
{ |
|
|
{ |
|
|
unsigned int type; /* 1U << n (see snd_codec.h) */ |
|
|
|
|
|
bgm_player_t player; /* Enumerated bgm player type */ |
|
|
|
|
|
int is_available; /* -1 means not present */ |
|
|
|
|
|
const char *ext; /* Expected file extension */ |
|
|
|
|
|
const char *dir; /* Where to look for music file */ |
|
|
|
|
|
struct music_handler_s *next; |
|
|
|
|
|
} music_handler_t; |
|
|
|
|
|
|
|
|
|
|
|
static music_handler_t wanted_handlers[] = |
|
|
|
|
|
{ |
|
|
|
|
|
{ CODECTYPE_VORBIS,BGM_STREAMER,-1, "ogg", MUSIC_DIRNAME, NULL }, |
|
|
|
|
|
{ CODECTYPE_OPUS, BGM_STREAMER, -1, "opus", MUSIC_DIRNAME, NULL }, |
|
|
|
|
|
{ CODECTYPE_MP3, BGM_STREAMER, -1, "mp3", MUSIC_DIRNAME, NULL }, |
|
|
|
|
|
{ CODECTYPE_FLAC, BGM_STREAMER, -1, "flac", MUSIC_DIRNAME, NULL }, |
|
|
|
|
|
{ CODECTYPE_WAV, BGM_STREAMER, -1, "wav", MUSIC_DIRNAME, NULL }, |
|
|
|
|
|
{ CODECTYPE_MOD, BGM_STREAMER, -1, "it", MUSIC_DIRNAME, NULL }, |
|
|
|
|
|
{ CODECTYPE_MOD, BGM_STREAMER, -1, "s3m", MUSIC_DIRNAME, NULL }, |
|
|
|
|
|
{ CODECTYPE_MOD, BGM_STREAMER, -1, "xm", MUSIC_DIRNAME, NULL }, |
|
|
|
|
|
{ CODECTYPE_MOD, BGM_STREAMER, -1, "mod", MUSIC_DIRNAME, NULL }, |
|
|
|
|
|
{ CODECTYPE_UMX, BGM_STREAMER, -1, "umx", MUSIC_DIRNAME, NULL }, |
|
|
|
|
|
{ CODECTYPE_NONE, BGM_NONE, -1, NULL, NULL, NULL } |
|
|
|
|
|
|
|
|
"wav", "flac", "ogg", "mp3" |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
static music_handler_t *music_handlers = NULL; |
|
|
|
|
|
|
|
|
|
|
|
#define ANY_CODECTYPE 0xFFFFFFFF |
|
|
|
|
|
#define CDRIP_TYPES (CODECTYPE_VORBIS | CODECTYPE_MP3 | CODECTYPE_FLAC | CODECTYPE_WAV | CODECTYPE_OPUS) |
|
|
|
|
|
#define CDRIPTYPE(x) (((x) & CDRIP_TYPES) != 0) |
|
|
|
|
|
|
|
|
|
|
|
static snd_stream_t *bgmstream = NULL; |
|
|
|
|
|
|
|
|
|
|
|
static void BGM_Play_f (void) |
|
|
static void BGM_Play_f (void) |
|
|
{ |
|
|
{ |
|
|
if (Cmd_Argc() == 2) |
|
|
if (Cmd_Argc() == 2) |
|
|
@ -124,8 +99,7 @@ static void BGM_Stop_f (void) |
|
|
|
|
|
|
|
|
qboolean BGM_Init (void) |
|
|
qboolean BGM_Init (void) |
|
|
{ |
|
|
{ |
|
|
music_handler_t *handlers = NULL; |
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
FMOD_RESULT result; |
|
|
|
|
|
|
|
|
Cvar_RegisterVariable(&bgm_extmusic); |
|
|
Cvar_RegisterVariable(&bgm_extmusic); |
|
|
Cmd_AddCommand("music", BGM_Play_f); |
|
|
Cmd_AddCommand("music", BGM_Play_f); |
|
|
@ -139,34 +113,17 @@ qboolean BGM_Init (void) |
|
|
|
|
|
|
|
|
bgmloop = true; |
|
|
bgmloop = true; |
|
|
|
|
|
|
|
|
for (i = 0; wanted_handlers[i].type != CODECTYPE_NONE; i++) |
|
|
|
|
|
|
|
|
if (!fmod_system) |
|
|
{ |
|
|
{ |
|
|
switch (wanted_handlers[i].player) |
|
|
|
|
|
{ |
|
|
|
|
|
case BGM_MIDIDRV: |
|
|
|
|
|
/* not supported in quake */ |
|
|
|
|
|
break; |
|
|
|
|
|
case BGM_STREAMER: |
|
|
|
|
|
wanted_handlers[i].is_available = |
|
|
|
|
|
S_CodecIsAvailable(wanted_handlers[i].type); |
|
|
|
|
|
break; |
|
|
|
|
|
case BGM_NONE: |
|
|
|
|
|
default: |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
if (wanted_handlers[i].is_available != -1) |
|
|
|
|
|
{ |
|
|
|
|
|
if (handlers) |
|
|
|
|
|
{ |
|
|
|
|
|
handlers->next = &wanted_handlers[i]; |
|
|
|
|
|
handlers = handlers->next; |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
music_handlers = &wanted_handlers[i]; |
|
|
|
|
|
handlers = music_handlers; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
Con_Printf("FMOD System not initialized! Cannot start FMOD music codec.\n"); |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
result = FMOD_System_CreateChannelGroup(fmod_system, "BGM", &bgm_channelGroup); |
|
|
|
|
|
if (result != FMOD_OK) |
|
|
|
|
|
{ |
|
|
|
|
|
Con_Printf("Failed to create FMOD music channel group: %s\n", FMOD_ErrorString(result)); |
|
|
|
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return true; |
|
|
return true; |
|
|
@ -175,46 +132,74 @@ qboolean BGM_Init (void) |
|
|
void BGM_Shutdown (void) |
|
|
void BGM_Shutdown (void) |
|
|
{ |
|
|
{ |
|
|
BGM_Stop(); |
|
|
BGM_Stop(); |
|
|
/* sever our connections to |
|
|
|
|
|
* midi_drv and snd_codec */ |
|
|
|
|
|
music_handlers = NULL; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void BGM_Play_noext (const char *filename, unsigned int allowed_types) |
|
|
|
|
|
|
|
|
static qboolean BGM_PlayStream(const char *filename) |
|
|
|
|
|
{ |
|
|
|
|
|
FILE *f; |
|
|
|
|
|
int len; |
|
|
|
|
|
FMOD_CREATESOUNDEXINFO exinfo; |
|
|
|
|
|
FMOD_RESULT result; |
|
|
|
|
|
|
|
|
|
|
|
len = COM_FOpenFile(filename, &f, NULL); |
|
|
|
|
|
fclose(f); |
|
|
|
|
|
if (len < 1) |
|
|
|
|
|
{ |
|
|
|
|
|
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); |
|
|
|
|
|
if (result != FMOD_OK || !bgm_sound) |
|
|
|
|
|
{ |
|
|
|
|
|
Con_Printf("Failed to create FMOD sound: %s\n", FMOD_ErrorString(result)); |
|
|
|
|
|
BGM_Stop(); |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
result = FMOD_System_PlaySound(fmod_system, bgm_sound, bgm_channelGroup, false, &bgm_channel); |
|
|
|
|
|
if (result != FMOD_OK || !bgm_channel) |
|
|
|
|
|
{ |
|
|
|
|
|
Con_Printf("Failed to play FMOD sound: %s\n", FMOD_ErrorString(result)); |
|
|
|
|
|
BGM_Stop(); |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (bgmloop) |
|
|
|
|
|
{ |
|
|
|
|
|
FMOD_Channel_SetMode(bgm_channel, FMOD_LOOP_NORMAL); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
FMOD_Channel_SetMode(bgm_channel, FMOD_LOOP_OFF); |
|
|
|
|
|
FMOD_Channel_SetLoopCount(bgm_channel, 0); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void BGM_Play_noext (const char *filename) |
|
|
{ |
|
|
{ |
|
|
char tmp[MAX_QPATH]; |
|
|
char tmp[MAX_QPATH]; |
|
|
music_handler_t *handler; |
|
|
|
|
|
|
|
|
|
|
|
handler = music_handlers; |
|
|
|
|
|
while (handler) |
|
|
|
|
|
|
|
|
for (int i = 0; i < sizeof(extensions) / sizeof(extensions[0]); ++i) |
|
|
{ |
|
|
{ |
|
|
if (! (handler->type & allowed_types)) |
|
|
|
|
|
{ |
|
|
|
|
|
handler = handler->next; |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
if (!handler->is_available) |
|
|
|
|
|
{ |
|
|
|
|
|
handler = handler->next; |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
q_snprintf(tmp, sizeof(tmp), "%s/%s.%s", |
|
|
|
|
|
handler->dir, filename, handler->ext); |
|
|
|
|
|
switch (handler->player) |
|
|
|
|
|
{ |
|
|
|
|
|
case BGM_MIDIDRV: |
|
|
|
|
|
/* not supported in quake */ |
|
|
|
|
|
break; |
|
|
|
|
|
case BGM_STREAMER: |
|
|
|
|
|
bgmstream = S_CodecOpenStreamType(tmp, handler->type); |
|
|
|
|
|
if (bgmstream) |
|
|
|
|
|
return; /* success */ |
|
|
|
|
|
break; |
|
|
|
|
|
case BGM_NONE: |
|
|
|
|
|
default: |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
handler = handler->next; |
|
|
|
|
|
|
|
|
q_snprintf(tmp, sizeof(tmp), "%s/%s.%s", MUSIC_DIRNAME, filename, extensions[i]); |
|
|
|
|
|
if (BGM_PlayStream(tmp)) |
|
|
|
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Con_Printf("Couldn't handle music file %s\n", filename); |
|
|
Con_Printf("Couldn't handle music file %s\n", filename); |
|
|
@ -224,13 +209,9 @@ void BGM_Play (const char *filename) |
|
|
{ |
|
|
{ |
|
|
char tmp[MAX_QPATH]; |
|
|
char tmp[MAX_QPATH]; |
|
|
const char *ext; |
|
|
const char *ext; |
|
|
music_handler_t *handler; |
|
|
|
|
|
|
|
|
|
|
|
BGM_Stop(); |
|
|
BGM_Stop(); |
|
|
|
|
|
|
|
|
if (music_handlers == NULL) |
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
if (!filename || !*filename) |
|
|
if (!filename || !*filename) |
|
|
{ |
|
|
{ |
|
|
Con_DPrintf("null music file name\n"); |
|
|
Con_DPrintf("null music file name\n"); |
|
|
@ -240,38 +221,13 @@ void BGM_Play (const char *filename) |
|
|
ext = COM_FileGetExtension(filename); |
|
|
ext = COM_FileGetExtension(filename); |
|
|
if (! *ext) /* try all things */ |
|
|
if (! *ext) /* try all things */ |
|
|
{ |
|
|
{ |
|
|
BGM_Play_noext(filename, ANY_CODECTYPE); |
|
|
|
|
|
|
|
|
BGM_Play_noext(filename); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
handler = music_handlers; |
|
|
|
|
|
while (handler) |
|
|
|
|
|
{ |
|
|
|
|
|
if (handler->is_available && |
|
|
|
|
|
!q_strcasecmp(ext, handler->ext)) |
|
|
|
|
|
break; |
|
|
|
|
|
handler = handler->next; |
|
|
|
|
|
} |
|
|
|
|
|
if (!handler) |
|
|
|
|
|
{ |
|
|
|
|
|
Con_Printf("Unhandled extension for %s\n", filename); |
|
|
|
|
|
|
|
|
q_snprintf(tmp, sizeof(tmp), "%s/%s", MUSIC_DIRNAME, filename); |
|
|
|
|
|
if (BGM_PlayStream(tmp)) |
|
|
return; |
|
|
return; |
|
|
} |
|
|
|
|
|
q_snprintf(tmp, sizeof(tmp), "%s/%s", handler->dir, filename); |
|
|
|
|
|
switch (handler->player) |
|
|
|
|
|
{ |
|
|
|
|
|
case BGM_MIDIDRV: |
|
|
|
|
|
/* not supported in quake */ |
|
|
|
|
|
break; |
|
|
|
|
|
case BGM_STREAMER: |
|
|
|
|
|
bgmstream = S_CodecOpenStreamType(tmp, handler->type); |
|
|
|
|
|
if (bgmstream) |
|
|
|
|
|
return; /* success */ |
|
|
|
|
|
break; |
|
|
|
|
|
case BGM_NONE: |
|
|
|
|
|
default: |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Con_Printf("Couldn't handle music file %s\n", filename); |
|
|
Con_Printf("Couldn't handle music file %s\n", filename); |
|
|
} |
|
|
} |
|
|
@ -287,169 +243,76 @@ void BGM_PlayCDtrack (byte track, qboolean looping) |
|
|
*/ |
|
|
*/ |
|
|
char tmp[MAX_QPATH]; |
|
|
char tmp[MAX_QPATH]; |
|
|
const char *ext; |
|
|
const char *ext; |
|
|
unsigned int path_id, prev_id, type; |
|
|
|
|
|
music_handler_t *handler; |
|
|
|
|
|
|
|
|
unsigned int path_id, prev_id; |
|
|
|
|
|
|
|
|
BGM_Stop(); |
|
|
BGM_Stop(); |
|
|
if (CDAudio_Play(track, looping) == 0) |
|
|
if (CDAudio_Play(track, looping) == 0) |
|
|
return; /* success */ |
|
|
return; /* success */ |
|
|
|
|
|
|
|
|
if (music_handlers == NULL) |
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
if (no_extmusic || !bgm_extmusic.value) |
|
|
if (no_extmusic || !bgm_extmusic.value) |
|
|
return; |
|
|
return; |
|
|
|
|
|
|
|
|
prev_id = 0; |
|
|
prev_id = 0; |
|
|
type = 0; |
|
|
|
|
|
ext = NULL; |
|
|
ext = NULL; |
|
|
handler = music_handlers; |
|
|
|
|
|
while (handler) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < sizeof(extensions) / sizeof(extensions[0]); ++i) |
|
|
{ |
|
|
{ |
|
|
if (! handler->is_available) |
|
|
|
|
|
goto _next; |
|
|
|
|
|
if (! CDRIPTYPE(handler->type)) |
|
|
|
|
|
goto _next; |
|
|
|
|
|
q_snprintf(tmp, sizeof(tmp), "%s/track%02d.%s", |
|
|
|
|
|
MUSIC_DIRNAME, (int)track, handler->ext); |
|
|
|
|
|
if (! COM_FileExists(tmp, &path_id)) |
|
|
|
|
|
goto _next; |
|
|
|
|
|
|
|
|
q_snprintf(tmp, sizeof(tmp), "%s/track%02d.%s", MUSIC_DIRNAME, (int)track, extensions[i]); |
|
|
|
|
|
if (!COM_FileExists(tmp, &path_id)) |
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
if (path_id > prev_id) |
|
|
if (path_id > prev_id) |
|
|
{ |
|
|
{ |
|
|
prev_id = path_id; |
|
|
prev_id = path_id; |
|
|
type = handler->type; |
|
|
|
|
|
ext = handler->ext; |
|
|
|
|
|
|
|
|
ext = extensions[i]; |
|
|
} |
|
|
} |
|
|
_next: |
|
|
|
|
|
handler = handler->next; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (ext == NULL) |
|
|
if (ext == NULL) |
|
|
Con_Printf("Couldn't find a cdrip for track %d\n", (int)track); |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
{ |
|
|
q_snprintf(tmp, sizeof(tmp), "%s/track%02d.%s", |
|
|
|
|
|
MUSIC_DIRNAME, (int)track, ext); |
|
|
|
|
|
bgmstream = S_CodecOpenStreamType(tmp, type); |
|
|
|
|
|
if (! bgmstream) |
|
|
|
|
|
Con_Printf("Couldn't handle music file %s\n", tmp); |
|
|
|
|
|
|
|
|
Con_Printf("Couldn't find a cdrip for track %d\n", (int)track); |
|
|
|
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
q_snprintf(tmp, sizeof(tmp), "%s/track%02d.%s", MUSIC_DIRNAME, (int)track, ext); |
|
|
|
|
|
if (!BGM_PlayStream(tmp)) |
|
|
|
|
|
Con_Printf("Couldn't handle music file %s\n", tmp); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void BGM_Stop (void) |
|
|
|
|
|
|
|
|
void BGM_Stop(void) |
|
|
{ |
|
|
{ |
|
|
if (bgmstream) |
|
|
|
|
|
|
|
|
if (bgm_channel) |
|
|
{ |
|
|
{ |
|
|
bgmstream->status = STREAM_NONE; |
|
|
|
|
|
S_CodecCloseStream(bgmstream); |
|
|
|
|
|
bgmstream = NULL; |
|
|
|
|
|
s_rawend = 0; |
|
|
|
|
|
|
|
|
FMOD_Channel_Stop(bgm_channel); |
|
|
|
|
|
bgm_channel = NULL; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void BGM_Pause (void) |
|
|
|
|
|
{ |
|
|
|
|
|
if (bgmstream) |
|
|
|
|
|
|
|
|
if (bgm_sound) |
|
|
|
|
|
{ |
|
|
|
|
|
FMOD_Sound_Release(bgm_sound); |
|
|
|
|
|
bgm_sound = NULL; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (bgm_data) |
|
|
{ |
|
|
{ |
|
|
if (bgmstream->status == STREAM_PLAY) |
|
|
|
|
|
bgmstream->status = STREAM_PAUSE; |
|
|
|
|
|
|
|
|
free(bgm_data); |
|
|
|
|
|
bgm_data = NULL; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void BGM_Resume (void) |
|
|
|
|
|
|
|
|
void BGM_Pause (void) |
|
|
{ |
|
|
{ |
|
|
if (bgmstream) |
|
|
|
|
|
|
|
|
if (bgm_channel) |
|
|
{ |
|
|
{ |
|
|
if (bgmstream->status == STREAM_PAUSE) |
|
|
|
|
|
bgmstream->status = STREAM_PLAY; |
|
|
|
|
|
|
|
|
FMOD_Channel_SetPaused(bgm_channel, true); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void BGM_UpdateStream (void) |
|
|
|
|
|
|
|
|
void BGM_Resume (void) |
|
|
{ |
|
|
{ |
|
|
qboolean did_rewind = false; |
|
|
|
|
|
int res; /* Number of bytes read. */ |
|
|
|
|
|
int bufferSamples; |
|
|
|
|
|
int fileSamples; |
|
|
|
|
|
int fileBytes; |
|
|
|
|
|
byte raw[16384]; |
|
|
|
|
|
|
|
|
|
|
|
if (bgmstream->status != STREAM_PLAY) |
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
/* don't bother playing anything if musicvolume is 0 */ |
|
|
|
|
|
if (bgmvolume.value <= 0) |
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
/* see how many samples should be copied into the raw buffer */ |
|
|
|
|
|
if (s_rawend < paintedtime) |
|
|
|
|
|
s_rawend = paintedtime; |
|
|
|
|
|
|
|
|
|
|
|
while (s_rawend < paintedtime + MAX_RAW_SAMPLES) |
|
|
|
|
|
|
|
|
if (bgm_channel) |
|
|
{ |
|
|
{ |
|
|
bufferSamples = MAX_RAW_SAMPLES - (s_rawend - paintedtime); |
|
|
|
|
|
|
|
|
|
|
|
/* decide how much data needs to be read from the file */ |
|
|
|
|
|
fileSamples = bufferSamples * bgmstream->info.rate / shm->speed; |
|
|
|
|
|
if (!fileSamples) |
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
/* our max buffer size */ |
|
|
|
|
|
fileBytes = fileSamples * (bgmstream->info.width * bgmstream->info.channels); |
|
|
|
|
|
if (fileBytes > (int) sizeof(raw)) |
|
|
|
|
|
{ |
|
|
|
|
|
fileBytes = (int) sizeof(raw); |
|
|
|
|
|
fileSamples = fileBytes / |
|
|
|
|
|
(bgmstream->info.width * bgmstream->info.channels); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Read */ |
|
|
|
|
|
res = S_CodecReadStream(bgmstream, fileBytes, raw); |
|
|
|
|
|
if (res < fileBytes) |
|
|
|
|
|
{ |
|
|
|
|
|
fileBytes = res; |
|
|
|
|
|
fileSamples = res / (bgmstream->info.width * bgmstream->info.channels); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (res > 0) /* data: add to raw buffer */ |
|
|
|
|
|
{ |
|
|
|
|
|
S_RawSamples(fileSamples, bgmstream->info.rate, |
|
|
|
|
|
bgmstream->info.width, |
|
|
|
|
|
bgmstream->info.channels, |
|
|
|
|
|
raw, bgmvolume.value); |
|
|
|
|
|
did_rewind = false; |
|
|
|
|
|
} |
|
|
|
|
|
else if (res == 0) /* EOF */ |
|
|
|
|
|
{ |
|
|
|
|
|
if (bgmloop) |
|
|
|
|
|
{ |
|
|
|
|
|
if (did_rewind) |
|
|
|
|
|
{ |
|
|
|
|
|
Con_Printf("Stream keeps returning EOF.\n"); |
|
|
|
|
|
BGM_Stop(); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
res = S_CodecRewindStream(bgmstream); |
|
|
|
|
|
if (res != 0) |
|
|
|
|
|
{ |
|
|
|
|
|
Con_Printf("Stream seek error (%i), stopping.\n", res); |
|
|
|
|
|
BGM_Stop(); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
did_rewind = true; |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
BGM_Stop(); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else /* res < 0: some read error */ |
|
|
|
|
|
{ |
|
|
|
|
|
Con_Printf("Stream read error (%i), stopping.\n", res); |
|
|
|
|
|
BGM_Stop(); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
FMOD_Channel_SetPaused(bgm_channel, false); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -461,9 +324,56 @@ void BGM_Update (void) |
|
|
Cvar_SetQuick (&bgmvolume, "0"); |
|
|
Cvar_SetQuick (&bgmvolume, "0"); |
|
|
else if (bgmvolume.value > 1) |
|
|
else if (bgmvolume.value > 1) |
|
|
Cvar_SetQuick (&bgmvolume, "1"); |
|
|
Cvar_SetQuick (&bgmvolume, "1"); |
|
|
|
|
|
|
|
|
old_volume = bgmvolume.value; |
|
|
old_volume = bgmvolume.value; |
|
|
} |
|
|
} |
|
|
if (bgmstream) |
|
|
|
|
|
BGM_UpdateStream (); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fmod_system) |
|
|
|
|
|
{ |
|
|
|
|
|
FMOD_System_Update(fmod_system); // TODO: move this to main FMOD sound handler (snd_fmod.c) |
|
|
|
|
|
|
|
|
|
|
|
if (bgm_channelGroup) |
|
|
|
|
|
{ |
|
|
|
|
|
FMOD_ChannelGroup_SetVolume(bgm_channelGroup, bgmvolume.value); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
|
|
|
|
qboolean BGM_Init(void) |
|
|
|
|
|
{ |
|
|
|
|
|
Con_Printf("BGM disabled at compile time\n"); |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void BGM_Shutdown(void) |
|
|
|
|
|
{ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void BGM_Play(const char *filename) |
|
|
|
|
|
{ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void BGM_Stop(void) |
|
|
|
|
|
{ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void BGM_Update(void) |
|
|
|
|
|
{ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void BGM_Pause(void) |
|
|
|
|
|
{ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void BGM_Resume(void) |
|
|
|
|
|
{ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void BGM_PlayCDtrack(byte track, qboolean looping) |
|
|
|
|
|
{ |
|
|
|
|
|
CDAudio_Play(track, looping); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#endif // USE_FMOD |