mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2024-12-28 05:11:34 +00:00
MusicPlus Core (positioning and fading) 2.2 -> 2.1 backport
This commit is contained in:
parent
34e403afcb
commit
c5ea6b5efe
22 changed files with 1175 additions and 91 deletions
|
@ -95,6 +95,37 @@ boolean I_SetSongSpeed(float speed)
|
|||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC SEEKING
|
||||
/// ------------------------
|
||||
|
||||
UINT32 I_GetSongLength(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongLoopPoint(UINT32 looppoint)
|
||||
{
|
||||
(void)looppoint;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongLoopPoint(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongPosition(UINT32 position)
|
||||
{
|
||||
(void)position;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongPosition(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC PLAYBACK
|
||||
/// ------------------------
|
||||
|
@ -139,3 +170,44 @@ void I_SetMusicVolume(INT32 volume)
|
|||
{
|
||||
(void)volume;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC FADING
|
||||
/// ------------------------
|
||||
|
||||
void I_SetInternalMusicVolume(UINT8 volume)
|
||||
{
|
||||
(void)volume;
|
||||
}
|
||||
|
||||
void I_StopFadingSong(void)
|
||||
{
|
||||
}
|
||||
|
||||
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)source_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeOutStopSong(UINT32 ms)
|
||||
{
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
|
||||
{
|
||||
(void)ms;
|
||||
(void)looping;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -3885,11 +3885,12 @@ static void Command_Tunes_f(void)
|
|||
{
|
||||
const char *tunearg;
|
||||
UINT16 tunenum, track = 0;
|
||||
UINT32 position = 0;
|
||||
const size_t argc = COM_Argc();
|
||||
|
||||
if (argc < 2) //tunes slot ...
|
||||
{
|
||||
CONS_Printf("tunes <name/num> [track] [speed] / <-show> / <-default> / <-none>:\n");
|
||||
CONS_Printf("tunes <name/num> [track] [speed] [position] / <-show> / <-default> / <-none>:\n");
|
||||
CONS_Printf(M_GetText("Play an arbitrary music lump. If a map number is used, 'MAP##M' is played.\n"));
|
||||
CONS_Printf(M_GetText("If the format supports multiple songs, you can specify which one to play.\n\n"));
|
||||
CONS_Printf(M_GetText("* With \"-show\", shows the currently playing tune and track.\n"));
|
||||
|
@ -3936,10 +3937,15 @@ static void Command_Tunes_f(void)
|
|||
snprintf(mapmusname, 7, "%sM", G_BuildMapName(tunenum));
|
||||
else
|
||||
strncpy(mapmusname, tunearg, 7);
|
||||
|
||||
if (argc > 4)
|
||||
position = (UINT32)atoi(COM_Argv(4));
|
||||
|
||||
mapmusname[6] = 0;
|
||||
mapmusflags = (track & MUSIC_TRACKMASK);
|
||||
mapmusposition = position;
|
||||
|
||||
S_ChangeMusic(mapmusname, mapmusflags, true);
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
|
||||
|
||||
if (argc > 3)
|
||||
{
|
||||
|
|
|
@ -1192,6 +1192,8 @@ static void readlevelheader(MYFILE *f, INT32 num)
|
|||
#endif
|
||||
else if (fastcmp(word, "MUSICTRACK"))
|
||||
mapheaderinfo[num-1]->mustrack = ((UINT16)i - 1);
|
||||
else if (fastcmp(word, "MUSICPOS"))
|
||||
mapheaderinfo[num-1]->muspos = (UINT32)get_number(word2);
|
||||
else if (fastcmp(word, "FORCECHARACTER"))
|
||||
{
|
||||
strlcpy(mapheaderinfo[num-1]->forcecharacter, word2, SKINNAMESIZE+1);
|
||||
|
@ -1483,6 +1485,11 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
|
|||
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musswitchflags), UNDO_NONE);
|
||||
cutscenes[num]->scene[scenenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK;
|
||||
}
|
||||
else if (fastcmp(word, "MUSICPOS"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musswitchposition), UNDO_NONE);
|
||||
cutscenes[num]->scene[scenenum].musswitchposition = (UINT32)get_number(word2);
|
||||
}
|
||||
else if (fastcmp(word, "MUSICLOOP"))
|
||||
{
|
||||
DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musicloop), UNDO_NONE);
|
||||
|
@ -6977,6 +6984,7 @@ struct {
|
|||
|
||||
// doomdef.h constants
|
||||
{"TICRATE",TICRATE},
|
||||
{"MUSICRATE",MUSICRATE},
|
||||
{"RING_DIST",RING_DIST},
|
||||
{"PUSHACCEL",PUSHACCEL},
|
||||
{"MODID",MODID}, // I don't know, I just thought it would be cool for a wad to potentially know what mod it was loaded into.
|
||||
|
@ -8264,6 +8272,9 @@ static inline int lib_getenum(lua_State *L)
|
|||
} else if (fastcmp(word,"mapmusflags")) {
|
||||
lua_pushinteger(L, mapmusflags);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"mapmusposition")) {
|
||||
lua_pushinteger(L, mapmusposition);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"server")) {
|
||||
if ((!multiplayer || !netgame) && !playeringame[serverplayer])
|
||||
return 0;
|
||||
|
|
|
@ -436,6 +436,37 @@ boolean I_SetSongSpeed(float speed)
|
|||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC SEEKING
|
||||
/// ------------------------
|
||||
|
||||
UINT32 I_GetSongLength(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongLoopPoint(UINT32 looppoint)
|
||||
{
|
||||
(void)looppoint;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongLoopPoint(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongPosition(UINT32 position)
|
||||
{
|
||||
(void)position;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongPosition(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC PLAYBACK
|
||||
/// ------------------------
|
||||
|
@ -543,3 +574,44 @@ int I_QrySongPlaying(int handle)
|
|||
return (midi_pos==-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC FADING
|
||||
/// ------------------------
|
||||
|
||||
void I_SetInternalMusicVolume(UINT8 volume)
|
||||
{
|
||||
(void)volume;
|
||||
}
|
||||
|
||||
void I_StopFadingSong(void)
|
||||
{
|
||||
}
|
||||
|
||||
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)source_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeOutStopSong(UINT32 ms)
|
||||
{
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
|
||||
{
|
||||
(void)ms;
|
||||
(void)looping;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -288,6 +288,8 @@ typedef enum
|
|||
#define NEWTICRATERATIO 1 // try 4 for 140 fps :)
|
||||
#define NEWTICRATE (TICRATE*NEWTICRATERATIO)
|
||||
|
||||
#define MUSICRATE 1000 // sound timing is calculated by milliseconds
|
||||
|
||||
#define RING_DIST 512*FRACUNIT // how close you need to be to a ring to attract it
|
||||
|
||||
#define PUSHACCEL (2*FRACUNIT) // Acceleration for MF2_SLIDEPUSH items.
|
||||
|
|
|
@ -33,8 +33,10 @@
|
|||
extern INT16 gamemap;
|
||||
extern char mapmusname[7];
|
||||
extern UINT16 mapmusflags;
|
||||
extern UINT32 mapmusposition;
|
||||
#define MUSIC_TRACKMASK 0x0FFF // ----************
|
||||
#define MUSIC_RELOADRESET 0x8000 // *---------------
|
||||
#define MUSIC_FORCERESET 0x4000 // -*--------------
|
||||
// Use other bits if necessary.
|
||||
|
||||
extern INT16 maptol;
|
||||
|
@ -145,6 +147,7 @@ typedef struct
|
|||
|
||||
char musswitch[7];
|
||||
UINT16 musswitchflags;
|
||||
UINT32 musswitchposition;
|
||||
|
||||
UINT8 fadecolor; // Color number for fade, 0 means don't do the first fade
|
||||
UINT8 fadeinid; // ID of the first fade, to a color -- ignored if fadecolor is 0
|
||||
|
@ -215,6 +218,7 @@ typedef struct
|
|||
INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end.
|
||||
char musname[7]; ///< Music track to play. "" for no music.
|
||||
UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
|
||||
UINT32 muspos; ///< Music position to jump to.
|
||||
char forcecharacter[17]; ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable.
|
||||
UINT8 weather; ///< 0 = sunny day, 1 = storm, 2 = snow, 3 = rain, 4 = blank, 5 = thunder w/o rain, 6 = rain w/o lightning, 7 = heat wave.
|
||||
INT16 skynum; ///< Sky number to use.
|
||||
|
|
|
@ -94,6 +94,37 @@ boolean I_SetSongSpeed(float speed)
|
|||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC SEEKING
|
||||
/// ------------------------
|
||||
|
||||
UINT32 I_GetSongLength(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongLoopPoint(UINT32 looppoint)
|
||||
{
|
||||
(void)looppoint;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongLoopPoint(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongPosition(UINT32 position)
|
||||
{
|
||||
(void)position;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongPosition(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC PLAYBACK
|
||||
/// ------------------------
|
||||
|
@ -142,3 +173,44 @@ boolean I_SetSongTrack(int track)
|
|||
(void)track;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC FADING
|
||||
/// ------------------------
|
||||
|
||||
void I_SetInternalMusicVolume(UINT8 volume)
|
||||
{
|
||||
(void)volume;
|
||||
}
|
||||
|
||||
void I_StopFadingSong(void)
|
||||
{
|
||||
}
|
||||
|
||||
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)source_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeOutStopSong(UINT32 ms)
|
||||
{
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
|
||||
{
|
||||
(void)ms;
|
||||
(void)looping;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1714,9 +1714,10 @@ static void F_AdvanceToNextScene(void)
|
|||
picypos = cutscenes[cutnum]->scene[scenenum].ycoord[picnum];
|
||||
|
||||
if (cutscenes[cutnum]->scene[scenenum].musswitch[0])
|
||||
S_ChangeMusic(cutscenes[cutnum]->scene[scenenum].musswitch,
|
||||
S_ChangeMusicEx(cutscenes[cutnum]->scene[scenenum].musswitch,
|
||||
cutscenes[cutnum]->scene[scenenum].musswitchflags,
|
||||
cutscenes[cutnum]->scene[scenenum].musicloop);
|
||||
cutscenes[cutnum]->scene[scenenum].musicloop,
|
||||
cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0);
|
||||
|
||||
// Fade to the next
|
||||
dofadenow = true;
|
||||
|
@ -1788,9 +1789,10 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
|
|||
stoptimer = 0;
|
||||
|
||||
if (cutscenes[cutnum]->scene[0].musswitch[0])
|
||||
S_ChangeMusic(cutscenes[cutnum]->scene[0].musswitch,
|
||||
S_ChangeMusicEx(cutscenes[cutnum]->scene[0].musswitch,
|
||||
cutscenes[cutnum]->scene[0].musswitchflags,
|
||||
cutscenes[cutnum]->scene[0].musicloop);
|
||||
cutscenes[cutnum]->scene[0].musicloop,
|
||||
cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0);
|
||||
else
|
||||
S_StopMusic();
|
||||
}
|
||||
|
|
12
src/g_game.c
12
src/g_game.c
|
@ -71,6 +71,7 @@ static void G_DoWorldDone(void);
|
|||
|
||||
char mapmusname[7]; // Music name
|
||||
UINT16 mapmusflags; // Track and reset bit
|
||||
UINT32 mapmusposition; // Position to jump to
|
||||
|
||||
INT16 gamemap = 1;
|
||||
INT16 maptol;
|
||||
|
@ -2187,17 +2188,6 @@ void G_PlayerReborn(INT32 player)
|
|||
if ((netgame || multiplayer) && !p->spectator)
|
||||
p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent
|
||||
|
||||
if (p-players == consoleplayer)
|
||||
{
|
||||
if (mapmusflags & MUSIC_RELOADRESET)
|
||||
{
|
||||
strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7);
|
||||
mapmusname[6] = 0;
|
||||
mapmusflags = mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK;
|
||||
}
|
||||
S_ChangeMusic(mapmusname, mapmusflags, true);
|
||||
}
|
||||
|
||||
if (gametype == GT_COOP)
|
||||
P_FindEmerald(); // scan for emeralds to hunt for
|
||||
|
||||
|
|
|
@ -146,6 +146,18 @@ boolean I_SongPaused(void);
|
|||
|
||||
boolean I_SetSongSpeed(float speed);
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC SEEKING
|
||||
/// ------------------------
|
||||
|
||||
UINT32 I_GetSongLength(void);
|
||||
|
||||
boolean I_SetSongLoopPoint(UINT32 looppoint);
|
||||
UINT32 I_GetSongLoopPoint(void);
|
||||
|
||||
boolean I_SetSongPosition(UINT32 position);
|
||||
UINT32 I_GetSongPosition(void);
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC PLAYBACK
|
||||
/// ------------------------
|
||||
|
@ -216,6 +228,17 @@ void I_SetMusicVolume(UINT8 volume);
|
|||
|
||||
boolean I_SetSongTrack(INT32 track);
|
||||
|
||||
/// ------------------------
|
||||
/// MUSIC FADING
|
||||
/// ------------------------
|
||||
|
||||
void I_SetInternalMusicVolume(UINT8 volume);
|
||||
void I_StopFadingSong(void);
|
||||
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
|
||||
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
|
||||
boolean I_FadeOutStopSong(UINT32 ms);
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping);
|
||||
|
||||
/// ------------------------
|
||||
// CD MUSIC I/O
|
||||
/// ------------------------
|
||||
|
|
|
@ -719,8 +719,14 @@ static int lib_pRestoreMusic(lua_State *L)
|
|||
NOHUD
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
else if (P_IsLocalPlayer(player))
|
||||
{
|
||||
P_RestoreMusic(player);
|
||||
return 0;
|
||||
lua_pushboolean(L, true);
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_pSpawnShieldOrb(lua_State *L)
|
||||
|
@ -1717,7 +1723,7 @@ static int lib_sChangeMusic(lua_State *L)
|
|||
{
|
||||
#ifdef MUSICSLOT_COMPATIBILITY
|
||||
const char *music_name;
|
||||
UINT32 music_num;
|
||||
UINT32 music_num, position, prefadems, fadeinms;
|
||||
char music_compat_name[7];
|
||||
|
||||
boolean looping;
|
||||
|
@ -1745,7 +1751,6 @@ static int lib_sChangeMusic(lua_State *L)
|
|||
music_name = luaL_checkstring(L, 1);
|
||||
}
|
||||
|
||||
|
||||
looping = (boolean)lua_opttrueboolean(L, 2);
|
||||
|
||||
#else
|
||||
|
@ -1770,9 +1775,18 @@ static int lib_sChangeMusic(lua_State *L)
|
|||
#endif
|
||||
music_flags = (UINT16)luaL_optinteger(L, 4, 0);
|
||||
|
||||
position = (UINT32)luaL_optinteger(L, 5, 0);
|
||||
prefadems = (UINT32)luaL_optinteger(L, 6, 0);
|
||||
fadeinms = (UINT32)luaL_optinteger(L, 7, 0);
|
||||
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
S_ChangeMusic(music_name, music_flags, looping);
|
||||
return 0;
|
||||
{
|
||||
S_ChangeMusicEx(music_name, music_flags, looping, position, prefadems, fadeinms);
|
||||
lua_pushboolean(L, true);
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_sSpeedMusic(lua_State *L)
|
||||
|
@ -1790,25 +1804,10 @@ static int lib_sSpeedMusic(lua_State *L)
|
|||
if (!player || P_IsLocalPlayer(player))
|
||||
lua_pushboolean(L, S_SpeedMusic(speed));
|
||||
else
|
||||
lua_pushboolean(L, false);
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_sStopMusic(lua_State *L)
|
||||
{
|
||||
player_t *player = NULL;
|
||||
NOHUD
|
||||
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
if (!player || P_IsLocalPlayer(player))
|
||||
S_StopMusic();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_sOriginPlaying(lua_State *L)
|
||||
{
|
||||
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
|
@ -2131,7 +2130,6 @@ static luaL_Reg lib[] = {
|
|||
{"S_StopSound",lib_sStopSound},
|
||||
{"S_ChangeMusic",lib_sChangeMusic},
|
||||
{"S_SpeedMusic",lib_sSpeedMusic},
|
||||
{"S_StopMusic",lib_sStopMusic},
|
||||
{"S_OriginPlaying",lib_sOriginPlaying},
|
||||
{"S_IdPlaying",lib_sIdPlaying},
|
||||
{"S_SoundPlaying",lib_sSoundPlaying},
|
||||
|
|
|
@ -43,6 +43,7 @@ enum hook {
|
|||
hook_PlayerMsg,
|
||||
hook_HurtMsg,
|
||||
hook_PlayerSpawn,
|
||||
hook_MusicChange,
|
||||
|
||||
hook_MAX // last hook
|
||||
};
|
||||
|
|
|
@ -54,6 +54,7 @@ const char *const hookNames[hook_MAX+1] = {
|
|||
"PlayerMsg",
|
||||
"HurtMsg",
|
||||
"PlayerSpawn",
|
||||
"MusicChange",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -1192,6 +1192,8 @@ static int mapheaderinfo_get(lua_State *L)
|
|||
lua_pushstring(L, header->musname);
|
||||
else if (fastcmp(field,"mustrack"))
|
||||
lua_pushinteger(L, header->mustrack);
|
||||
else if (fastcmp(field,"muspos"))
|
||||
lua_pushinteger(L, header->muspos);
|
||||
else if (fastcmp(field,"forcecharacter"))
|
||||
lua_pushstring(L, header->forcecharacter);
|
||||
else if (fastcmp(field,"weather"))
|
||||
|
|
|
@ -185,6 +185,8 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
|
|||
mapheaderinfo[num]->musname[6] = 0;
|
||||
DEH_WriteUndoline("MUSICTRACK", va("%d", mapheaderinfo[num]->mustrack), UNDO_NONE);
|
||||
mapheaderinfo[num]->mustrack = 0;
|
||||
DEH_WriteUndoline("MUSICPOS", va("%d", mapheaderinfo[num]->mustrack), UNDO_NONE);
|
||||
mapheaderinfo[num]->muspos = 0;
|
||||
DEH_WriteUndoline("FORCECHARACTER", va("%d", mapheaderinfo[num]->forcecharacter), UNDO_NONE);
|
||||
mapheaderinfo[num]->forcecharacter[0] = '\0';
|
||||
DEH_WriteUndoline("WEATHER", va("%d", mapheaderinfo[num]->weather), UNDO_NONE);
|
||||
|
|
|
@ -2428,6 +2428,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
if (!(line->flags & ML_BLOCKMONSTERS))
|
||||
mapmusflags |= MUSIC_RELOADRESET;
|
||||
|
||||
mapmusposition = 0;
|
||||
|
||||
S_ChangeMusic(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4));
|
||||
|
||||
// Except, you can use the ML_BLOCKMONSTERS flag to change this behavior.
|
||||
|
|
|
@ -1124,13 +1124,13 @@ void P_RestoreMusic(player_t *player)
|
|||
if (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)
|
||||
{
|
||||
S_SpeedMusic(1.4f);
|
||||
S_ChangeMusic(mapmusname, mapmusflags, true);
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
|
||||
}
|
||||
else
|
||||
S_ChangeMusicInternal("shoes", true);
|
||||
}
|
||||
else
|
||||
S_ChangeMusic(mapmusname, mapmusflags, true);
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
145
src/s_sound.c
145
src/s_sound.c
|
@ -37,6 +37,10 @@ extern INT32 msg_id;
|
|||
#include "r_sky.h" // skyflatnum
|
||||
#include "p_local.h" // camera info
|
||||
|
||||
#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS)
|
||||
#include "lua_hook.h" // MusicChange hook
|
||||
#endif
|
||||
|
||||
#ifdef HW3SOUND
|
||||
// 3D Sound Interface
|
||||
#include "hardware/hw3sound.h"
|
||||
|
@ -1219,6 +1223,12 @@ static void *music_data;
|
|||
static UINT16 music_flags;
|
||||
static boolean music_looping;
|
||||
|
||||
static char queue_name[7];
|
||||
static UINT16 queue_flags;
|
||||
static boolean queue_looping;
|
||||
static UINT32 queue_position;
|
||||
static UINT32 queue_fadeinms;
|
||||
|
||||
/// ------------------------
|
||||
/// Music Status
|
||||
/// ------------------------
|
||||
|
@ -1253,6 +1263,11 @@ musictype_t S_MusicType(void)
|
|||
return I_SongType();
|
||||
}
|
||||
|
||||
const char *S_MusicName(void)
|
||||
{
|
||||
return music_name;
|
||||
}
|
||||
|
||||
boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping)
|
||||
{
|
||||
if (!I_SongPlaying())
|
||||
|
@ -1283,6 +1298,35 @@ boolean S_SpeedMusic(float speed)
|
|||
return I_SetSongSpeed(speed);
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Music Seeking
|
||||
/// ------------------------
|
||||
|
||||
UINT32 S_GetMusicLength(void)
|
||||
{
|
||||
return I_GetSongLength();
|
||||
}
|
||||
|
||||
boolean S_SetMusicLoopPoint(UINT32 looppoint)
|
||||
{
|
||||
return I_SetSongLoopPoint(looppoint);
|
||||
}
|
||||
|
||||
UINT32 S_GetMusicLoopPoint(void)
|
||||
{
|
||||
return I_GetSongLoopPoint();
|
||||
}
|
||||
|
||||
boolean S_SetMusicPosition(UINT32 position)
|
||||
{
|
||||
return I_SetSongPosition(position);
|
||||
}
|
||||
|
||||
UINT32 S_GetMusicPosition(void)
|
||||
{
|
||||
return I_GetSongPosition();
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Music Playback
|
||||
/// ------------------------
|
||||
|
@ -1355,12 +1399,13 @@ static void S_UnloadMusic(void)
|
|||
music_looping = false;
|
||||
}
|
||||
|
||||
static boolean S_PlayMusic(boolean looping)
|
||||
static boolean S_PlayMusic(boolean looping, UINT32 fadeinms)
|
||||
{
|
||||
if (S_MusicDisabled())
|
||||
return false;
|
||||
|
||||
if (!I_PlaySong(looping))
|
||||
if ((!fadeinms && !I_PlaySong(looping)) ||
|
||||
(fadeinms && !I_FadeInPlaySong(fadeinms, looping)))
|
||||
{
|
||||
S_UnloadMusic();
|
||||
return false;
|
||||
|
@ -1370,7 +1415,27 @@ static boolean S_PlayMusic(boolean looping)
|
|||
return true;
|
||||
}
|
||||
|
||||
void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping)
|
||||
static void S_QueueMusic(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 fadeinms)
|
||||
{
|
||||
strncpy(queue_name, mmusic, 7);
|
||||
queue_flags = mflags;
|
||||
queue_looping = looping;
|
||||
queue_position = position;
|
||||
queue_fadeinms = fadeinms;
|
||||
}
|
||||
|
||||
static void S_ClearQueue(void)
|
||||
{
|
||||
queue_name[0] = queue_flags = queue_looping = queue_position = queue_fadeinms = 0;
|
||||
}
|
||||
|
||||
static void S_ChangeMusicToQueue(void)
|
||||
{
|
||||
S_ChangeMusicEx(queue_name, queue_flags, queue_looping, queue_position, 0, queue_fadeinms);
|
||||
S_ClearQueue();
|
||||
}
|
||||
|
||||
void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms)
|
||||
{
|
||||
#if defined (DC) || defined (_WIN32_WCE) || defined (PSP) || defined(GP2X)
|
||||
S_ClearSfx();
|
||||
|
@ -1379,34 +1444,63 @@ void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping)
|
|||
if (S_MusicDisabled())
|
||||
return;
|
||||
|
||||
char newmusic[7];
|
||||
strncpy(newmusic, mmusic, 7);
|
||||
#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS)
|
||||
if(LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms))
|
||||
return;
|
||||
#endif
|
||||
newmusic[6] = 0;
|
||||
|
||||
// No Music (empty string)
|
||||
if (mmusic[0] == 0)
|
||||
if (newmusic[0] == 0)
|
||||
{
|
||||
if (prefadems)
|
||||
I_FadeSong(0, prefadems, &S_StopMusic);
|
||||
else
|
||||
S_StopMusic();
|
||||
return;
|
||||
}
|
||||
|
||||
if (strnicmp(music_name, mmusic, 6))
|
||||
if (prefadems && S_MusicPlaying()) // queue music change for after fade // allow even if the music is the same
|
||||
{
|
||||
S_StopMusic(); // shutdown old music
|
||||
CONS_Debug(DBG_DETAILED, "Now fading out song %s\n", music_name);
|
||||
S_QueueMusic(newmusic, mflags, looping, position, fadeinms);
|
||||
I_FadeSong(0, prefadems, S_ChangeMusicToQueue);
|
||||
return;
|
||||
}
|
||||
else if (strnicmp(music_name, newmusic, 6) || (mflags & MUSIC_FORCERESET))
|
||||
{
|
||||
CONS_Debug(DBG_DETAILED, "Now playing song %s\n", newmusic);
|
||||
|
||||
if (!S_LoadMusic(mmusic))
|
||||
S_StopMusic();
|
||||
|
||||
if (!S_LoadMusic(newmusic))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Music %.6s could not be loaded!\n", mmusic);
|
||||
CONS_Alert(CONS_ERROR, "Music %.6s could not be loaded!\n", newmusic);
|
||||
return;
|
||||
}
|
||||
|
||||
music_flags = mflags;
|
||||
music_looping = looping;
|
||||
|
||||
if (!S_PlayMusic(looping))
|
||||
if (!S_PlayMusic(looping, fadeinms))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Music %.6s could not be played!\n", mmusic);
|
||||
CONS_Alert(CONS_ERROR, "Music %.6s could not be played!\n", newmusic);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (position)
|
||||
I_SetSongPosition(position);
|
||||
|
||||
I_SetSongTrack(mflags & MUSIC_TRACKMASK);
|
||||
}
|
||||
else if (fadeinms) // let fades happen with same music
|
||||
{
|
||||
I_SetSongPosition(position);
|
||||
I_FadeSong(100, fadeinms, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void S_StopMusic(void)
|
||||
{
|
||||
|
@ -1480,6 +1574,32 @@ void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume)
|
|||
}
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Music Fading
|
||||
/// ------------------------
|
||||
|
||||
void S_SetInternalMusicVolume(INT32 volume)
|
||||
{
|
||||
I_SetInternalMusicVolume(min(max(volume, 0), 100));
|
||||
}
|
||||
|
||||
void S_StopFadingMusic(void)
|
||||
{
|
||||
I_StopFadingSong();
|
||||
}
|
||||
|
||||
boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 ms)
|
||||
{
|
||||
if (source_volume < 0)
|
||||
return I_FadeSong(target_volume, ms, NULL);
|
||||
else
|
||||
return I_FadeSongFromVolume(target_volume, source_volume, ms, false);
|
||||
}
|
||||
|
||||
boolean S_FadeOutStopMusic(UINT32 ms)
|
||||
{
|
||||
return I_FadeSong(0, ms, &S_StopMusic);
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Init & Others
|
||||
|
@ -1497,9 +1617,10 @@ void S_Start(void)
|
|||
strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7);
|
||||
mapmusname[6] = 0;
|
||||
mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK);
|
||||
mapmusposition = mapheaderinfo[gamemap-1]->muspos;
|
||||
}
|
||||
|
||||
if (cv_resetmusic.value)
|
||||
S_StopMusic();
|
||||
S_ChangeMusic(mapmusname, mapmusflags, true);
|
||||
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
|
||||
}
|
||||
|
|
|
@ -108,29 +108,49 @@ boolean S_MusicDisabled(void);
|
|||
boolean S_MusicPlaying(void);
|
||||
boolean S_MusicPaused(void);
|
||||
musictype_t S_MusicType(void);
|
||||
const char *S_MusicName(void);
|
||||
boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping);
|
||||
boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi);
|
||||
#define S_DigExists(a) S_MusicExists(a, false, true)
|
||||
#define S_MIDIExists(a) S_MusicExists(a, true, false)
|
||||
|
||||
|
||||
//
|
||||
// Music Properties
|
||||
// Music Effects
|
||||
//
|
||||
|
||||
// Set Speed of Music
|
||||
boolean S_SpeedMusic(float speed);
|
||||
|
||||
//
|
||||
// Music Routines
|
||||
// Music Seeking
|
||||
//
|
||||
|
||||
// Get Length of Music
|
||||
UINT32 S_GetMusicLength(void);
|
||||
|
||||
// Set LoopPoint of Music
|
||||
boolean S_SetMusicLoopPoint(UINT32 looppoint);
|
||||
|
||||
// Get LoopPoint of Music
|
||||
UINT32 S_GetMusicLoopPoint(void);
|
||||
|
||||
// Set Position of Music
|
||||
boolean S_SetMusicPosition(UINT32 position);
|
||||
|
||||
// Get Position of Music
|
||||
UINT32 S_GetMusicPosition(void);
|
||||
|
||||
//
|
||||
// Music Playback
|
||||
//
|
||||
|
||||
// Start music track, arbitrary, given its name, and set whether looping
|
||||
// note: music flags 12 bits for tracknum (gme, other formats with more than one track)
|
||||
// 13-15 aren't used yet
|
||||
// and the last bit we ignore (internal game flag for resetting music on reload)
|
||||
#define S_ChangeMusicInternal(a,b) S_ChangeMusic(a,0,b)
|
||||
void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping);
|
||||
void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms);
|
||||
#define S_ChangeMusicInternal(a,b) S_ChangeMusicEx(a,0,b,0,0,0)
|
||||
#define S_ChangeMusic(a,b,c) S_ChangeMusicEx(a,b,c,0,0,0)
|
||||
|
||||
// Stops the music.
|
||||
void S_StopMusic(void);
|
||||
|
@ -139,6 +159,17 @@ void S_StopMusic(void);
|
|||
void S_PauseAudio(void);
|
||||
void S_ResumeAudio(void);
|
||||
|
||||
//
|
||||
// Music Fading
|
||||
//
|
||||
|
||||
void S_SetInternalMusicVolume(INT32 volume);
|
||||
void S_StopFadingMusic(void);
|
||||
boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 ms);
|
||||
#define S_FadeMusic(a, b) S_FadeMusicFromVolume(a, -1, b)
|
||||
#define S_FadeInChangeMusic(a,b,c,d) S_ChangeMusicEx(a,b,c,0,0,d)
|
||||
boolean S_FadeOutStopMusic(UINT32 ms);
|
||||
|
||||
//
|
||||
// Updates music & sounds
|
||||
//
|
||||
|
|
|
@ -69,15 +69,41 @@
|
|||
UINT8 sound_started = false;
|
||||
|
||||
static Mix_Music *music;
|
||||
static UINT8 music_volume, sfx_volume;
|
||||
static UINT8 music_volume, sfx_volume, internal_volume;
|
||||
static float loop_point;
|
||||
static float song_length; // length in seconds
|
||||
static boolean songpaused;
|
||||
static UINT32 music_bytes;
|
||||
static boolean is_looping;
|
||||
|
||||
// fading
|
||||
static boolean is_fading;
|
||||
static UINT8 fading_source;
|
||||
static UINT8 fading_target;
|
||||
static UINT32 fading_timer;
|
||||
static UINT32 fading_duration;
|
||||
static INT32 fading_id;
|
||||
static void (*fading_callback)(void);
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
static Music_Emu *gme;
|
||||
static INT32 current_track;
|
||||
#endif
|
||||
|
||||
static void var_cleanup(void)
|
||||
{
|
||||
loop_point = song_length =\
|
||||
music_bytes = fading_source = fading_target =\
|
||||
fading_timer = fading_duration = 0;
|
||||
|
||||
songpaused = is_looping =\
|
||||
is_fading = false;
|
||||
|
||||
fading_callback = NULL;
|
||||
|
||||
internal_volume = 100;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Audio System
|
||||
/// ------------------------
|
||||
|
@ -99,6 +125,8 @@ void I_StartupSound(void)
|
|||
return;
|
||||
}
|
||||
|
||||
var_cleanup();
|
||||
|
||||
music = NULL;
|
||||
music_volume = sfx_volume = 0;
|
||||
|
||||
|
@ -323,6 +351,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
|
|||
len = (info->play_length * 441 / 10) << 2;
|
||||
mem = malloc(len);
|
||||
gme_play(emu, len >> 1, mem);
|
||||
gme_free_info(info);
|
||||
gme_delete(emu);
|
||||
|
||||
return Mix_QuickLoad_RAW((Uint8 *)mem, len);
|
||||
|
@ -395,6 +424,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
|
|||
len = (info->play_length * 441 / 10) << 2;
|
||||
mem = malloc(len);
|
||||
gme_play(emu, len >> 1, mem);
|
||||
gme_free_info(info);
|
||||
gme_delete(emu);
|
||||
|
||||
return Mix_QuickLoad_RAW((Uint8 *)mem, len);
|
||||
|
@ -447,14 +477,96 @@ void I_SetSfxVolume(UINT8 volume)
|
|||
sfx_volume = volume;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Music Utilities
|
||||
/// ------------------------
|
||||
|
||||
static UINT32 get_real_volume(UINT8 volume)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (I_SongType() == MU_MID)
|
||||
// HACK: Until we stop using native MIDI,
|
||||
// disable volume changes
|
||||
return ((UINT32)31*128/31); // volume = 31
|
||||
else
|
||||
#endif
|
||||
// convert volume to mixer's 128 scale
|
||||
// then apply internal_volume as a percentage
|
||||
return ((UINT32)volume*128/31) * (UINT32)internal_volume / 100;
|
||||
}
|
||||
|
||||
static UINT32 get_adjusted_position(UINT32 position)
|
||||
{
|
||||
// all in milliseconds
|
||||
UINT32 length = I_GetSongLength();
|
||||
UINT32 looppoint = I_GetSongLoopPoint();
|
||||
if (length)
|
||||
return position >= length ? (position % (length-looppoint)) : position;
|
||||
else
|
||||
return position;
|
||||
}
|
||||
|
||||
static void do_fading_callback()
|
||||
{
|
||||
if (fading_callback)
|
||||
(*fading_callback)();
|
||||
fading_callback = NULL;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Music Hooks
|
||||
/// ------------------------
|
||||
|
||||
static void count_music_bytes(int chan, void *stream, int len, void *udata)
|
||||
{
|
||||
if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || I_SongType() == MU_MID)
|
||||
return;
|
||||
music_bytes += len;
|
||||
}
|
||||
|
||||
static void music_loop(void)
|
||||
{
|
||||
if (is_looping)
|
||||
{
|
||||
Mix_PlayMusic(music, 0);
|
||||
Mix_SetMusicPosition(loop_point);
|
||||
music_bytes = loop_point*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition)
|
||||
}
|
||||
else
|
||||
I_StopSong();
|
||||
}
|
||||
|
||||
static UINT32 music_fade(UINT32 interval, void *param)
|
||||
{
|
||||
if (!is_fading ||
|
||||
internal_volume == fading_target ||
|
||||
fading_duration == 0)
|
||||
{
|
||||
I_StopFadingSong();
|
||||
do_fading_callback();
|
||||
return 0;
|
||||
}
|
||||
else if (songpaused) // don't decrement timer
|
||||
return interval;
|
||||
else if ((fading_timer -= 10) <= 0)
|
||||
{
|
||||
internal_volume = fading_target;
|
||||
Mix_VolumeMusic(get_real_volume(music_volume));
|
||||
I_StopFadingSong();
|
||||
do_fading_callback();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT8 delta = abs(fading_target - fading_source);
|
||||
double factor = (double)(fading_duration - fading_timer) / (double)fading_duration;
|
||||
if (fading_target < fading_source)
|
||||
internal_volume = max(min(internal_volume, fading_source - (UINT8)round(delta * factor)), fading_target);
|
||||
else if (fading_target > fading_source)
|
||||
internal_volume = min(max(internal_volume, fading_source + (UINT8)round(delta * factor)), fading_target);
|
||||
Mix_VolumeMusic(get_real_volume(music_volume));
|
||||
return interval;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
|
@ -474,7 +586,7 @@ static void mix_gme(void *udata, Uint8 *stream, int len)
|
|||
|
||||
// apply volume to stream
|
||||
for (i = 0, p = (short *)stream; i < len/2; i++, p++)
|
||||
*p = ((INT32)*p) * music_volume*2 / 42;
|
||||
*p = ((INT32)*p) * (music_volume*internal_volume/100)*2 / 42;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -552,6 +664,194 @@ boolean I_SetSongSpeed(float speed)
|
|||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// MUSIC SEEKING
|
||||
/// ------------------------
|
||||
|
||||
UINT32 I_GetSongLength(void)
|
||||
{
|
||||
INT32 length;
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
if (gme)
|
||||
{
|
||||
gme_info_t *info;
|
||||
gme_err_t gme_e = gme_track_info(gme, &info, current_track);
|
||||
|
||||
if (gme_e != NULL)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e);
|
||||
length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// reconstruct info->play_length, from GME source
|
||||
// we only want intro + 1 loop, not 2
|
||||
length = info->length;
|
||||
if (length <= 0)
|
||||
{
|
||||
length = info->intro_length + info->loop_length; // intro + 1 loop
|
||||
if (length <= 0)
|
||||
length = 150 * 1000; // 2.5 minutes
|
||||
}
|
||||
}
|
||||
|
||||
gme_free_info(info);
|
||||
return max(length, 0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!music || I_SongType() == MU_MOD || I_SongType() == MU_MID)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
// VERY IMPORTANT to set your LENGTHMS= in your song files, folks!
|
||||
// SDL mixer can't read music length itself.
|
||||
length = (UINT32)(song_length*1000);
|
||||
if (!length)
|
||||
CONS_Debug(DBG_DETAILED, "Getting music length: music is missing LENGTHMS= tag. Needed for seeking.\n");
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
boolean I_SetSongLoopPoint(UINT32 looppoint)
|
||||
{
|
||||
if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || I_SongType() == MU_MID || !is_looping)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
UINT32 length = I_GetSongLength();
|
||||
|
||||
if (length > 0)
|
||||
looppoint %= length;
|
||||
|
||||
loop_point = max((float)(looppoint / 1000.0L), 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 I_GetSongLoopPoint(void)
|
||||
{
|
||||
#ifdef HAVE_LIBGME
|
||||
if (gme)
|
||||
{
|
||||
INT32 looppoint;
|
||||
gme_info_t *info;
|
||||
gme_err_t gme_e = gme_track_info(gme, &info, current_track);
|
||||
|
||||
if (gme_e != NULL)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e);
|
||||
looppoint = 0;
|
||||
}
|
||||
else
|
||||
looppoint = info->intro_length > 0 ? info->intro_length : 0;
|
||||
|
||||
gme_free_info(info);
|
||||
return max(looppoint, 0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!music || I_SongType() == MU_MOD || I_SongType() == MU_MID)
|
||||
return 0;
|
||||
else
|
||||
return (UINT32)(loop_point * 1000);
|
||||
}
|
||||
|
||||
boolean I_SetSongPosition(UINT32 position)
|
||||
{
|
||||
UINT32 length;
|
||||
#ifdef HAVE_LIBGME
|
||||
if (gme)
|
||||
{
|
||||
// this is unstable, so fail silently
|
||||
return true;
|
||||
// this isn't required technically, but GME thread-locks for a second
|
||||
// if you seek too high from the counter
|
||||
// length = I_GetSongLength();
|
||||
// if (length)
|
||||
// position = get_adjusted_position(position);
|
||||
|
||||
// SDL_LockAudio();
|
||||
// gme_err_t gme_e = gme_seek(gme, position);
|
||||
// SDL_UnlockAudio();
|
||||
|
||||
// if (gme_e != NULL)
|
||||
// {
|
||||
// CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e);
|
||||
// return false;
|
||||
// }
|
||||
// else
|
||||
// return true;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!music || I_SongType() == MU_MID)
|
||||
return false;
|
||||
else if (I_SongType() == MU_MOD)
|
||||
return Mix_SetMusicPosition(position); // Goes by channels
|
||||
else
|
||||
{
|
||||
// Because SDL mixer can't identify song length, if you have
|
||||
// a position input greater than the real length, then
|
||||
// music_bytes becomes inaccurate.
|
||||
|
||||
length = I_GetSongLength(); // get it in MS
|
||||
if (length)
|
||||
position = get_adjusted_position(position);
|
||||
|
||||
Mix_RewindMusic(); // needed for mp3
|
||||
if(Mix_SetMusicPosition((float)(position/1000.0L)) == 0)
|
||||
music_bytes = position/1000.0L*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition)
|
||||
else
|
||||
// NOTE: This block fires on incorrect song format,
|
||||
// NOT if position input is greater than song length.
|
||||
music_bytes = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 I_GetSongPosition(void)
|
||||
{
|
||||
#ifdef HAVE_LIBGME
|
||||
if (gme)
|
||||
{
|
||||
INT32 position = gme_tell(gme);
|
||||
|
||||
gme_info_t *info;
|
||||
gme_err_t gme_e = gme_track_info(gme, &info, current_track);
|
||||
|
||||
if (gme_e != NULL)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e);
|
||||
return position;
|
||||
}
|
||||
else
|
||||
{
|
||||
// adjust position, since GME's counter keeps going past loop
|
||||
if (info->length > 0)
|
||||
position %= info->length;
|
||||
else if (info->intro_length + info->loop_length > 0)
|
||||
position = position >= (info->intro_length + info->loop_length) ? (position % info->loop_length) : position;
|
||||
else
|
||||
position %= 150 * 1000; // 2.5 minutes
|
||||
}
|
||||
|
||||
gme_free_info(info);
|
||||
return max(position, 0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!music || I_SongType() == MU_MID)
|
||||
return 0;
|
||||
else
|
||||
return music_bytes/44100.0L*1000.0L/4; //assume 44.1khz
|
||||
// 4 = byte length for 16-bit samples (AUDIO_S16SYS), stereo (2-channel)
|
||||
// This is hardcoded in I_StartupSound. Other formats for factor:
|
||||
// 8M: 1 | 8S: 2 | 16M: 2 | 16S: 4
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// Music Playback
|
||||
/// ------------------------
|
||||
|
@ -561,9 +861,21 @@ boolean I_LoadSong(char *data, size_t len)
|
|||
const char *key1 = "LOOP";
|
||||
const char *key2 = "POINT=";
|
||||
const char *key3 = "MS=";
|
||||
const char *key4 = "LENGTHMS=";
|
||||
const size_t key1len = strlen(key1);
|
||||
const size_t key2len = strlen(key2);
|
||||
const size_t key3len = strlen(key3);
|
||||
const size_t key4len = strlen(key4);
|
||||
|
||||
// for mp3 wide chars
|
||||
const char *key1w = "L\0O\0O\0P\0";
|
||||
const char *key2w = "P\0O\0I\0N\0T\0\0\0\xFF\xFE";
|
||||
const char *key3w = "M\0S\0\0\0\xFF\xFE";
|
||||
const char *key4w = "L\0E\0N\0G\0T\0H\0M\0S\0\0\0\xFF\xFE";
|
||||
const char *wterm = "\0\0";
|
||||
char wval[10];
|
||||
|
||||
size_t wstart, wp;
|
||||
char *p = data;
|
||||
|
||||
if (music
|
||||
|
@ -573,6 +885,8 @@ boolean I_LoadSong(char *data, size_t len)
|
|||
)
|
||||
I_UnloadSong();
|
||||
|
||||
var_cleanup();
|
||||
|
||||
#ifdef HAVE_LIBGME
|
||||
if ((UINT8)data[0] == 0x1F
|
||||
&& (UINT8)data[1] == 0x8B)
|
||||
|
@ -675,14 +989,21 @@ boolean I_LoadSong(char *data, size_t len)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (I_SongType() == MU_MP3)
|
||||
{
|
||||
CONS_Debug(DBG_BASIC, "MP3 songs are unsupported and may crash! Use OGG instead.\n");
|
||||
CONS_Debug(DBG_DETAILED, "MP3 songs are unsupported and may crash! Use OGG instead.\n");
|
||||
}
|
||||
|
||||
// Find the OGG loop point.
|
||||
loop_point = 0.0f;
|
||||
song_length = 0.0f;
|
||||
|
||||
while ((UINT32)(p - data) < len)
|
||||
{
|
||||
if (strncmp(p++, key1, key1len))
|
||||
continue;
|
||||
p += key1len-1; // skip OOP (the L was skipped in strncmp)
|
||||
if (!loop_point && !strncmp(p, key1, key1len))
|
||||
{
|
||||
p += key1len; // skip LOOP
|
||||
if (!strncmp(p, key2, key2len)) // is it LOOPPOINT=?
|
||||
{
|
||||
p += key2len; // skip POINT=
|
||||
|
@ -698,9 +1019,66 @@ boolean I_LoadSong(char *data, size_t len)
|
|||
loop_point = (float)(atoi(p) / 1000.0L); // LOOPMS works by real time, as miliseconds.
|
||||
// Everything that uses LOOPMS will work perfectly with SDL_Mixer.
|
||||
}
|
||||
// Neither?! Continue searching.
|
||||
}
|
||||
else if (!song_length && !strncmp(p, key4, key4len)) // is it LENGTHMS=?
|
||||
{
|
||||
p += key4len; // skip LENGTHMS
|
||||
song_length = (float)(atoi(p) / 1000.0L);
|
||||
}
|
||||
// below: search MP3 or other tags that use wide char encoding
|
||||
else if (!loop_point && !memcmp(p, key1w, key1len*2)) // LOOP wide char
|
||||
{
|
||||
p += key1len*2;
|
||||
if (!memcmp(p, key2w, (key2len+1)*2)) // POINT= wide char
|
||||
{
|
||||
p += (key2len+1)*2;
|
||||
wstart = (size_t)p;
|
||||
wp = 0;
|
||||
while (wp < 9 && memcmp(p, wterm, 2))
|
||||
{
|
||||
wval[wp] = *p;
|
||||
p += 2;
|
||||
wp = ((size_t)(p-wstart))/2;
|
||||
}
|
||||
wval[min(wp, 9)] = 0;
|
||||
loop_point = (float)((44.1L+atoi(wval) / 44100.0L));
|
||||
}
|
||||
else if (!memcmp(p, key3w, (key3len+1)*2)) // MS= wide char
|
||||
{
|
||||
p += (key3len+1)*2;
|
||||
wstart = (size_t)p;
|
||||
wp = 0;
|
||||
while (wp < 9 && memcmp(p, wterm, 2))
|
||||
{
|
||||
wval[wp] = *p;
|
||||
p += 2;
|
||||
wp = ((size_t)(p-wstart))/2;
|
||||
}
|
||||
wval[min(wp, 9)] = 0;
|
||||
loop_point = (float)(atoi(wval) / 1000.0L);
|
||||
}
|
||||
}
|
||||
else if (!song_length && !memcmp(p, key4w, (key4len+1)*2)) // LENGTHMS= wide char
|
||||
{
|
||||
p += (key4len+1)*2;
|
||||
wstart = (size_t)p;
|
||||
wp = 0;
|
||||
while (wp < 9 && memcmp(p, wterm, 2))
|
||||
{
|
||||
wval[wp] = *p;
|
||||
p += 2;
|
||||
wp = ((size_t)(p-wstart))/2;
|
||||
}
|
||||
wval[min(wp, 9)] = 0;
|
||||
song_length = (float)(atoi(wval) / 1000.0L);
|
||||
}
|
||||
|
||||
if (loop_point && song_length && song_length > loop_point) // Got what we needed
|
||||
// the last case is a sanity check, in case the wide char searches were false matches.
|
||||
break;
|
||||
else // continue searching
|
||||
p++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -737,15 +1115,30 @@ boolean I_PlaySong(boolean looping)
|
|||
if (!music)
|
||||
return false;
|
||||
|
||||
if (Mix_PlayMusic(music, looping && loop_point == 0.0f ? -1 : 0) == -1)
|
||||
if (!song_length && (I_SongType() == MU_OGG || I_SongType() == MU_MP3 || I_SongType() == MU_FLAC))
|
||||
CONS_Debug(DBG_DETAILED, "This song is missing a LENGTHMS= tag! Required to make seeking work properly.\n");
|
||||
|
||||
if (I_SongType() != MU_MOD && I_SongType() != MU_MID && Mix_PlayMusic(music, 0) == -1)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError());
|
||||
return false;
|
||||
}
|
||||
else if ((I_SongType() == MU_MOD || I_SongType() == MU_MID) && Mix_PlayMusic(music, looping ? -1 : 0) == -1) // if MOD, loop forever
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError());
|
||||
return false;
|
||||
}
|
||||
Mix_VolumeMusic((UINT32)music_volume*128/31);
|
||||
|
||||
if (loop_point != 0.0f)
|
||||
Mix_HookMusicFinished(music_loop);
|
||||
is_looping = looping;
|
||||
|
||||
I_SetMusicVolume(music_volume);
|
||||
|
||||
if (I_SongType() != MU_MOD && I_SongType() != MU_MID)
|
||||
Mix_HookMusicFinished(music_loop); // don't bother counting if MOD
|
||||
|
||||
if(I_SongType() != MU_MOD && I_SongType() != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL))
|
||||
CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -760,19 +1153,40 @@ void I_StopSong(void)
|
|||
#endif
|
||||
if (music)
|
||||
{
|
||||
var_cleanup();
|
||||
I_StopFadingSong();
|
||||
Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes);
|
||||
Mix_HookMusicFinished(NULL);
|
||||
Mix_HaltMusic();
|
||||
}
|
||||
}
|
||||
|
||||
void I_PauseSong(void)
|
||||
void I_PauseSong()
|
||||
{
|
||||
if(I_SongType() == MU_MID) // really, SDL Mixer? why can't you pause MIDI???
|
||||
return;
|
||||
|
||||
if(I_SongType() != MU_GME && I_SongType() != MU_MOD && I_SongType() != MU_MID)
|
||||
Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes);
|
||||
|
||||
Mix_PauseMusic();
|
||||
songpaused = true;
|
||||
}
|
||||
|
||||
void I_ResumeSong(void)
|
||||
void I_ResumeSong()
|
||||
{
|
||||
if (I_SongType() == MU_MID)
|
||||
return;
|
||||
|
||||
if (I_SongType() != MU_GME && I_SongType() != MU_MOD && I_SongType() != MU_MID)
|
||||
{
|
||||
while(Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes) != 0) { }
|
||||
// HACK: fixes issue of multiple effect callbacks being registered
|
||||
|
||||
if(music && I_SongType() != MU_MOD && I_SongType() != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL))
|
||||
CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError());
|
||||
}
|
||||
|
||||
Mix_ResumeMusic();
|
||||
songpaused = false;
|
||||
}
|
||||
|
@ -791,7 +1205,7 @@ void I_SetMusicVolume(UINT8 volume)
|
|||
#endif
|
||||
music_volume = volume;
|
||||
|
||||
Mix_VolumeMusic((UINT32)music_volume*128/31);
|
||||
Mix_VolumeMusic(get_real_volume(music_volume));
|
||||
}
|
||||
|
||||
boolean I_SetSongTrack(int track)
|
||||
|
@ -820,9 +1234,100 @@ boolean I_SetSongTrack(int track)
|
|||
SDL_UnlockAudio();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (I_SongType() == MU_MOD)
|
||||
return !Mix_SetMusicPosition(track);
|
||||
(void)track;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// MUSIC FADING
|
||||
/// ------------------------
|
||||
|
||||
void I_SetInternalMusicVolume(UINT8 volume)
|
||||
{
|
||||
internal_volume = volume;
|
||||
if (!I_SongPlaying())
|
||||
return;
|
||||
Mix_VolumeMusic(get_real_volume(music_volume));
|
||||
}
|
||||
|
||||
void I_StopFadingSong(void)
|
||||
{
|
||||
if (fading_id)
|
||||
SDL_RemoveTimer(fading_id);
|
||||
is_fading = false;
|
||||
fading_source = fading_target = fading_timer = fading_duration = fading_id = 0;
|
||||
}
|
||||
|
||||
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void))
|
||||
{
|
||||
INT16 volume_delta;
|
||||
|
||||
source_volume = min(source_volume, 100);
|
||||
volume_delta = (INT16)(target_volume - source_volume);
|
||||
|
||||
I_StopFadingSong();
|
||||
|
||||
if (!ms && volume_delta)
|
||||
{
|
||||
I_SetInternalMusicVolume(target_volume);
|
||||
if (callback)
|
||||
(*callback)();
|
||||
return true;
|
||||
|
||||
}
|
||||
else if (!volume_delta)
|
||||
{
|
||||
if (callback)
|
||||
(*callback)();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Round MS to nearest 10
|
||||
// If n - lower > higher - n, then round up
|
||||
ms = (ms - ((ms / 10) * 10) > (((ms / 10) * 10) + 10) - ms) ?
|
||||
(((ms / 10) * 10) + 10) // higher
|
||||
: ((ms / 10) * 10); // lower
|
||||
|
||||
if (!ms)
|
||||
I_SetInternalMusicVolume(target_volume);
|
||||
else if (source_volume != target_volume)
|
||||
{
|
||||
fading_id = SDL_AddTimer(10, music_fade, NULL);
|
||||
if (fading_id)
|
||||
{
|
||||
is_fading = true;
|
||||
fading_timer = fading_duration = ms;
|
||||
fading_source = source_volume;
|
||||
fading_target = target_volume;
|
||||
fading_callback = callback;
|
||||
|
||||
if (internal_volume != source_volume)
|
||||
I_SetInternalMusicVolume(source_volume);
|
||||
}
|
||||
}
|
||||
|
||||
return is_fading;
|
||||
}
|
||||
|
||||
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void))
|
||||
{
|
||||
return I_FadeSongFromVolume(target_volume, internal_volume, ms, callback);
|
||||
}
|
||||
|
||||
boolean I_FadeOutStopSong(UINT32 ms)
|
||||
{
|
||||
return I_FadeSongFromVolume(0, internal_volume, ms, &I_StopSong);
|
||||
}
|
||||
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
|
||||
{
|
||||
if (I_PlaySong(looping))
|
||||
return I_FadeSongFromVolume(100, 0, ms, NULL);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
#endif
|
|
@ -1368,6 +1368,37 @@ boolean I_SetSongSpeed(float speed)
|
|||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC SEEKING
|
||||
/// ------------------------
|
||||
|
||||
UINT32 I_GetSongLength(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongLoopPoint(UINT32 looppoint)
|
||||
{
|
||||
(void)looppoint;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongLoopPoint(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongPosition(UINT32 position)
|
||||
{
|
||||
(void)position;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongPosition(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC PLAYBACK
|
||||
/// ------------------------
|
||||
|
@ -1436,6 +1467,47 @@ boolean I_SetSongTrack(int track)
|
|||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// MUSIC FADING
|
||||
/// ------------------------
|
||||
|
||||
void I_SetInternalMusicVolume(UINT8 volume)
|
||||
{
|
||||
(void)volume;
|
||||
}
|
||||
|
||||
void I_StopFadingSong(void)
|
||||
{
|
||||
}
|
||||
|
||||
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)source_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeOutStopSong(UINT32 ms)
|
||||
{
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
|
||||
{
|
||||
(void)ms;
|
||||
(void)looping;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
// MUSIC LOADING AND CLEANUP
|
||||
// \todo Split logic between loading and playing,
|
||||
|
|
|
@ -810,6 +810,60 @@ void I_SetMusicVolume(UINT8 volume)
|
|||
FMR_MUSIC(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0));
|
||||
}
|
||||
|
||||
UINT32 I_GetSongLength()
|
||||
{
|
||||
if (midimode)
|
||||
return 0;
|
||||
UINT32 length;
|
||||
e = FMOD_Sound_GetLength(music_stream, length, FMOD_TIMEUNIT_MS);
|
||||
return length;
|
||||
}
|
||||
|
||||
boolean I_SetSongLoopPoint(UINT32 looppoint)
|
||||
{
|
||||
(void)looppoint;
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT32 I_GetSongLoopPoint(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongPosition(UINT32 position)
|
||||
{
|
||||
if(midimode)
|
||||
// Dummy out; this works for some MIDI, but not others.
|
||||
// SDL does not support this for any MIDI.
|
||||
return false;
|
||||
FMOD_RESULT e;
|
||||
e = FMOD_Channel_SetPosition(music_channel, position, FMOD_TIMEUNIT_MS);
|
||||
if (e == FMOD_OK)
|
||||
return true;
|
||||
else if (e == FMOD_ERR_UNSUPPORTED // Only music modules, numbnuts!
|
||||
|| e == FMOD_ERR_INVALID_POSITION) // Out-of-bounds!
|
||||
return false;
|
||||
else // Congrats, you horribly broke it somehow
|
||||
{
|
||||
FMR_MUSIC(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 I_GetSongPosition(void)
|
||||
{
|
||||
if(midimode)
|
||||
// Dummy out because unsupported, even though FMOD does this correctly.
|
||||
return 0;
|
||||
FMOD_RESULT e;
|
||||
unsigned int fmposition = 0;
|
||||
e = FMOD_Channel_GetPosition(music_channel, &fmposition, FMOD_TIMEUNIT_MS);
|
||||
if (e == FMOD_OK)
|
||||
return (UINT32)fmposition;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean I_SetSongTrack(INT32 track)
|
||||
{
|
||||
if (track != current_track) // If the track's already playing, then why bother?
|
||||
|
@ -854,3 +908,44 @@ boolean I_SetSongTrack(INT32 track)
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ------------------------
|
||||
/// MUSIC FADING
|
||||
/// ------------------------
|
||||
|
||||
void I_SetInternalMusicVolume(UINT8 volume)
|
||||
{
|
||||
(void)volume;
|
||||
}
|
||||
|
||||
void I_StopFadingSong(void)
|
||||
{
|
||||
}
|
||||
|
||||
boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void));
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)source_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
|
||||
{
|
||||
(void)target_volume;
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeOutStopSong(UINT32 ms)
|
||||
{
|
||||
(void)ms;
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
|
||||
{
|
||||
(void)ms;
|
||||
(void)looping;
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue