2019-11-24 20:45:15 -08:00
|
|
|
/*
|
|
|
|
* Background music handling for Quakespasm (adapted from uHexen2)
|
|
|
|
* Handles streaming music as raw sound samples and runs the midi driver
|
|
|
|
*
|
|
|
|
* Copyright (C) 1999-2005 Id Software, Inc.
|
|
|
|
* Copyright (C) 2010-2018 O.Sezer <sezero@users.sourceforge.net>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or (at
|
|
|
|
* your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
*
|
|
|
|
* See the GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2019-12-02 07:07:37 -08:00
|
|
|
#include "q_defs.h"
|
2019-11-24 20:45:15 -08:00
|
|
|
#include "snd_codec.h"
|
|
|
|
#include "bgmusic.h"
|
2019-11-24 22:55:37 -08:00
|
|
|
#include "cdaudio.h"
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-12-12 19:10:12 -08:00
|
|
|
#define MUSIC_DIRNAME "music"
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-12-12 19:10:12 -08:00
|
|
|
bool bgm_loop;
|
|
|
|
cvar_t bgm_extmusic = {"bgm_extmusic", "1", CVAR_ARCHIVE};
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-12-12 19:10:12 -08:00
|
|
|
static bool no_extmusic = false;
|
|
|
|
static float old_volume = -1.0f;
|
2019-11-24 20:45:15 -08:00
|
|
|
|
|
|
|
typedef struct music_handler_s
|
|
|
|
{
|
2019-12-12 19:10:12 -08:00
|
|
|
uint32_t type;
|
|
|
|
const char *ext;
|
2019-11-24 20:45:15 -08:00
|
|
|
} music_handler_t;
|
|
|
|
|
2019-12-12 19:10:12 -08:00
|
|
|
static music_handler_t music_handlers[] =
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-12-12 19:10:12 -08:00
|
|
|
#if USE_CODEC_FLAC
|
|
|
|
{ CODECTYPE_FLAC, "flac" },
|
|
|
|
#endif
|
|
|
|
#if USE_CODEC_OPUS
|
|
|
|
{ CODECTYPE_OPUS, "opus" },
|
|
|
|
#endif
|
|
|
|
#if USE_CODEC_VORBIS
|
|
|
|
{ CODECTYPE_VORBIS, "ogg" },
|
|
|
|
#endif
|
|
|
|
#if USE_CODEC_MOD
|
|
|
|
{ CODECTYPE_MOD, "it" },
|
|
|
|
{ CODECTYPE_MOD, "s3m" },
|
|
|
|
{ CODECTYPE_MOD, "xm" },
|
|
|
|
{ CODECTYPE_MOD, "mod" },
|
|
|
|
{ CODECTYPE_UMX, "umx" },
|
|
|
|
#endif
|
|
|
|
{ CODECTYPE_NONE, NULL }
|
2019-11-24 20:45:15 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
static snd_stream_t *bgmstream = NULL;
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
static void BGM_Play_f(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
if(Cmd_Argc() == 2)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
BGM_Play(Cmd_Argv(1));
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
Con_Printf("music <musicfile>\n");
|
2019-11-24 20:45:15 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
static void BGM_Pause_f(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
BGM_Pause();
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
static void BGM_Resume_f(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
BGM_Resume();
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
static void BGM_Loop_f(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
if(Cmd_Argc() == 2)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-12-12 19:10:12 -08:00
|
|
|
if(q_strcasecmp(Cmd_Argv(1), "0") == 0 ||
|
|
|
|
q_strcasecmp(Cmd_Argv(1), "off") == 0)
|
2019-12-07 09:10:06 -08:00
|
|
|
bgm_loop = false;
|
2019-11-25 17:40:18 -08:00
|
|
|
else if(q_strcasecmp(Cmd_Argv(1), "1") == 0 ||
|
2019-12-12 19:10:12 -08:00
|
|
|
q_strcasecmp(Cmd_Argv(1), "on") == 0)
|
2019-12-07 09:10:06 -08:00
|
|
|
bgm_loop = true;
|
2019-11-25 17:40:18 -08:00
|
|
|
else if(q_strcasecmp(Cmd_Argv(1), "toggle") == 0)
|
2019-12-07 09:10:06 -08:00
|
|
|
bgm_loop = !bgm_loop;
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
2019-12-07 09:10:06 -08:00
|
|
|
if(bgm_loop)
|
2019-11-24 20:45:15 -08:00
|
|
|
Con_Printf("Music will be looped\n");
|
|
|
|
else
|
|
|
|
Con_Printf("Music will not be looped\n");
|
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
static void BGM_Stop_f(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
BGM_Stop();
|
|
|
|
}
|
|
|
|
|
2019-12-12 19:10:12 -08:00
|
|
|
void BGM_Init(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
Cvar_RegisterVariable(&bgm_extmusic);
|
|
|
|
Cmd_AddCommand("music", BGM_Play_f);
|
|
|
|
Cmd_AddCommand("music_pause", BGM_Pause_f);
|
|
|
|
Cmd_AddCommand("music_resume", BGM_Resume_f);
|
|
|
|
Cmd_AddCommand("music_loop", BGM_Loop_f);
|
|
|
|
Cmd_AddCommand("music_stop", BGM_Stop_f);
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(COM_CheckParm("-noextmusic") != 0)
|
2019-11-24 20:45:15 -08:00
|
|
|
no_extmusic = true;
|
|
|
|
|
2019-12-07 09:10:06 -08:00
|
|
|
bgm_loop = true;
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-12-12 19:10:12 -08:00
|
|
|
CDAudio_Init();
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
void BGM_Shutdown(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
BGM_Stop();
|
2019-11-25 17:40:18 -08:00
|
|
|
/* sever our connections to
|
|
|
|
* midi_drv and snd_codec */
|
|
|
|
CDAudio_Shutdown();
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
static void BGM_Play_noext(const char *filename, uint32_t allowed_types)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
char tmp[MAX_QPATH];
|
|
|
|
music_handler_t *handler;
|
|
|
|
|
2019-12-12 19:10:12 -08:00
|
|
|
for(handler = music_handlers; handler->type != CODECTYPE_NONE; handler++)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!(handler->type & allowed_types))
|
2019-11-24 20:45:15 -08:00
|
|
|
continue;
|
2019-12-12 19:10:12 -08:00
|
|
|
q_snprintf(tmp, sizeof(tmp), "%s/%s.%s", MUSIC_DIRNAME, filename, handler->ext);
|
|
|
|
bgmstream = S_CodecOpenStreamType(tmp, handler->type);
|
|
|
|
if(bgmstream)
|
|
|
|
return;
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
Con_Printf("Couldn't handle music file %s\n", filename);
|
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
void BGM_Play(const char *filename)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
char tmp[MAX_QPATH];
|
|
|
|
const char *ext;
|
|
|
|
music_handler_t *handler;
|
|
|
|
|
|
|
|
BGM_Stop();
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!filename || !*filename)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
Con_DPrintf("null music file name\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ext = COM_FileGetExtension(filename);
|
2019-11-25 17:40:18 -08:00
|
|
|
if(! *ext) /* try all things */
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
BGM_Play_noext(filename, ANY_CODECTYPE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-12-12 19:10:12 -08:00
|
|
|
for(handler = music_handlers; handler->type != CODECTYPE_NONE; handler++)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-12-12 19:10:12 -08:00
|
|
|
if(!q_strcasecmp(ext, handler->ext))
|
2019-11-24 20:45:15 -08:00
|
|
|
break;
|
|
|
|
}
|
2019-12-12 19:10:12 -08:00
|
|
|
if(handler->type == CODECTYPE_NONE)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
Con_Printf("Unhandled extension for %s\n", filename);
|
|
|
|
return;
|
|
|
|
}
|
2019-12-12 19:10:12 -08:00
|
|
|
q_snprintf(tmp, sizeof(tmp), "%s/%s", MUSIC_DIRNAME, filename);
|
|
|
|
bgmstream = S_CodecOpenStreamType(tmp, handler->type);
|
|
|
|
if(bgmstream)
|
|
|
|
return; /* success */
|
2019-11-24 20:45:15 -08:00
|
|
|
|
|
|
|
Con_Printf("Couldn't handle music file %s\n", filename);
|
|
|
|
}
|
|
|
|
|
2019-12-07 09:10:06 -08:00
|
|
|
void BGM_PlayCDTrack(byte track, bool looping)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
/* instead of searching by the order of music_handlers, do so by
|
|
|
|
* the order of searchpath priority: the file from the searchpath
|
|
|
|
* with the highest path_id is most likely from our own gamedir
|
|
|
|
* itself. This way, if a mod has track02 as a *.mp3 file, which
|
|
|
|
* is below *.ogg in the music_handler order, the mp3 will still
|
|
|
|
* have priority over track02.ogg from, say, id1.
|
|
|
|
*/
|
2019-11-24 20:45:15 -08:00
|
|
|
char tmp[MAX_QPATH];
|
|
|
|
const char *ext;
|
2019-11-25 14:05:12 -08:00
|
|
|
uint32_t path_id, prev_id, type;
|
2019-11-24 20:45:15 -08:00
|
|
|
music_handler_t *handler;
|
|
|
|
|
|
|
|
BGM_Stop();
|
2019-11-25 17:40:18 -08:00
|
|
|
if(CDAudio_Play(track, looping) == 0)
|
2019-11-24 22:41:23 -08:00
|
|
|
return; /* success */
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(no_extmusic || !bgm_extmusic.value)
|
2019-11-24 20:45:15 -08:00
|
|
|
return;
|
|
|
|
|
|
|
|
prev_id = 0;
|
|
|
|
type = 0;
|
|
|
|
ext = NULL;
|
2019-12-12 19:10:12 -08:00
|
|
|
for(handler = music_handlers; handler->type != CODECTYPE_NONE; handler++)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-12-12 19:10:12 -08:00
|
|
|
if(!CDRIPTYPE(handler->type))
|
|
|
|
continue;
|
|
|
|
printf("%s\n", handler->ext);
|
|
|
|
q_snprintf(tmp, sizeof(tmp), "%s/track%02i.%s", MUSIC_DIRNAME, track, handler->ext);
|
|
|
|
if(!COM_FileExists(tmp, &path_id))
|
|
|
|
continue;
|
2019-11-25 17:40:18 -08:00
|
|
|
if(path_id > prev_id)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
prev_id = path_id;
|
|
|
|
type = handler->type;
|
|
|
|
ext = handler->ext;
|
|
|
|
}
|
|
|
|
}
|
2019-11-25 17:40:18 -08:00
|
|
|
if(ext == NULL)
|
2019-11-25 16:56:15 -08:00
|
|
|
Con_Printf("Couldn't find a cdrip for track %" PRIi32 "\n", (int32_t)track);
|
2019-11-24 20:45:15 -08:00
|
|
|
else
|
|
|
|
{
|
2019-12-12 19:10:12 -08:00
|
|
|
q_snprintf(tmp, sizeof(tmp), "%s/track%02i.%s", MUSIC_DIRNAME, track, ext);
|
2019-11-24 20:45:15 -08:00
|
|
|
bgmstream = S_CodecOpenStreamType(tmp, type);
|
2019-11-25 17:40:18 -08:00
|
|
|
if(! bgmstream)
|
2019-11-24 20:45:15 -08:00
|
|
|
Con_Printf("Couldn't handle music file %s\n", tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
void BGM_Stop(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
if(bgmstream)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
bgmstream->status = STREAM_NONE;
|
|
|
|
S_CodecCloseStream(bgmstream);
|
|
|
|
bgmstream = NULL;
|
|
|
|
s_rawend = 0;
|
|
|
|
}
|
2019-11-24 22:55:37 -08:00
|
|
|
CDAudio_Stop();
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
void BGM_Pause(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
if(bgmstream)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
if(bgmstream->status == STREAM_PLAY)
|
2019-11-24 20:45:15 -08:00
|
|
|
bgmstream->status = STREAM_PAUSE;
|
|
|
|
}
|
2019-11-25 17:40:18 -08:00
|
|
|
CDAudio_Pause();
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
void BGM_Resume(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
if(bgmstream)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
if(bgmstream->status == STREAM_PAUSE)
|
2019-11-24 20:45:15 -08:00
|
|
|
bgmstream->status = STREAM_PLAY;
|
|
|
|
}
|
2019-11-25 17:40:18 -08:00
|
|
|
CDAudio_Resume();
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
static void BGM_UpdateStream(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 15:28:38 -08:00
|
|
|
bool did_rewind = false;
|
2019-11-25 17:40:18 -08:00
|
|
|
int32_t res; /* Number of bytes read. */
|
|
|
|
int32_t bufferSamples;
|
|
|
|
int32_t fileSamples;
|
|
|
|
int32_t fileBytes;
|
|
|
|
byte raw[16384];
|
2019-11-24 20:45:15 -08:00
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(bgmstream->status != STREAM_PLAY)
|
2019-11-24 20:45:15 -08:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* don't bother playing anything if musicvolume is 0 */
|
2019-11-25 17:40:18 -08:00
|
|
|
if(bgmvolume.value <= 0)
|
2019-11-24 20:45:15 -08:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* see how many samples should be copied into the raw buffer */
|
2019-11-25 17:40:18 -08:00
|
|
|
if(s_rawend < paintedtime)
|
2019-11-24 20:45:15 -08:00
|
|
|
s_rawend = paintedtime;
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
while(s_rawend < paintedtime + MAX_RAW_SAMPLES)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
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;
|
2019-11-25 17:40:18 -08:00
|
|
|
if(!fileSamples)
|
2019-11-24 20:45:15 -08:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* our max buffer size */
|
|
|
|
fileBytes = fileSamples * (bgmstream->info.width * bgmstream->info.channels);
|
2019-11-25 17:40:18 -08:00
|
|
|
if(fileBytes > (int32_t) sizeof(raw))
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 16:49:58 -08:00
|
|
|
fileBytes = (int32_t) sizeof(raw);
|
2019-11-24 20:45:15 -08:00
|
|
|
fileSamples = fileBytes /
|
2019-11-25 17:40:18 -08:00
|
|
|
(bgmstream->info.width * bgmstream->info.channels);
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Read */
|
|
|
|
res = S_CodecReadStream(bgmstream, fileBytes, raw);
|
2019-11-25 17:40:18 -08:00
|
|
|
if(res < fileBytes)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
fileBytes = res;
|
|
|
|
fileSamples = res / (bgmstream->info.width * bgmstream->info.channels);
|
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
if(res > 0) /* data: add to raw buffer */
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
S_RawSamples(fileSamples, bgmstream->info.rate,
|
2019-11-25 17:40:18 -08:00
|
|
|
bgmstream->info.width,
|
|
|
|
bgmstream->info.channels,
|
|
|
|
raw, bgmvolume.value);
|
2019-11-24 20:45:15 -08:00
|
|
|
did_rewind = false;
|
|
|
|
}
|
2019-11-25 17:40:18 -08:00
|
|
|
else if(res == 0) /* EOF */
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-12-07 09:10:06 -08:00
|
|
|
if(bgm_loop)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
if(did_rewind)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
|
|
|
Con_Printf("Stream keeps returning EOF.\n");
|
|
|
|
BGM_Stop();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
res = S_CodecRewindStream(bgmstream);
|
2019-11-25 17:40:18 -08:00
|
|
|
if(res != 0)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 16:56:15 -08:00
|
|
|
Con_Printf("Stream seek error (%" PRIi32 "), stopping.\n", res);
|
2019-11-24 20:45:15 -08:00
|
|
|
BGM_Stop();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
did_rewind = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BGM_Stop();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2019-11-25 17:40:18 -08:00
|
|
|
else /* res < 0: some read error */
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 16:56:15 -08:00
|
|
|
Con_Printf("Stream read error (%" PRIi32 "), stopping.\n", res);
|
2019-11-24 20:45:15 -08:00
|
|
|
BGM_Stop();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-25 17:40:18 -08:00
|
|
|
void BGM_Update(void)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
if(old_volume != bgmvolume.value)
|
2019-11-24 20:45:15 -08:00
|
|
|
{
|
2019-11-25 17:40:18 -08:00
|
|
|
if(bgmvolume.value < 0)
|
|
|
|
Cvar_SetQuick(&bgmvolume, "0");
|
|
|
|
else if(bgmvolume.value > 1)
|
|
|
|
Cvar_SetQuick(&bgmvolume, "1");
|
2019-11-24 20:45:15 -08:00
|
|
|
old_volume = bgmvolume.value;
|
|
|
|
}
|
2019-11-25 17:40:18 -08:00
|
|
|
if(bgmstream)
|
|
|
|
BGM_UpdateStream();
|
2019-11-24 22:55:37 -08:00
|
|
|
|
|
|
|
CDAudio_Update();
|
2019-11-24 20:45:15 -08:00
|
|
|
}
|
|
|
|
|