Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Libretro
tyrquake
Commits
93468f1b
Commit
93468f1b
authored
Dec 09, 2016
by
Adriano Moura
Browse files
Import as much of the bgm sytem as possible
parent
8759023d
Changes
26
Show whitespace changes
Inline
Side-by-side
Makefile
View file @
93468f1b
...
@@ -3,6 +3,21 @@ FRONTEND_SUPPORTS_RGB565=1
...
@@ -3,6 +3,21 @@ FRONTEND_SUPPORTS_RGB565=1
TARGET_NAME
=
tyrquake
TARGET_NAME
=
tyrquake
STATIC_LINKING
=
0
STATIC_LINKING
=
0
USE_CODEC_WAVE
=
1
USE_CODEC_FLAC
=
1
USE_CODEC_MP3
=
0
USE_CODEC_VORBIS
=
1
USE_CODEC_OPUS
=
0
# either mikmod (preferred) or modplug, not both
USE_CODEC_MIKMOD
=
0
USE_CODEC_MODPLUG
=
0
USE_CODEC_UMX
=
0
# which library to use for mp3 decoding: mad or mpg123
MP3LIB
=
mad
# which library to use for ogg decoding: vorbis or tremor
VORBISLIB
=
vorbis
ifeq
($(platform),)
ifeq
($(platform),)
platform
=
unix
platform
=
unix
ifeq
($(shell uname -a),)
ifeq
($(shell uname -a),)
...
@@ -265,9 +280,76 @@ else
...
@@ -265,9 +280,76 @@ else
CFLAGS
+=
-O3
-DNDEBUG
CFLAGS
+=
-O3
-DNDEBUG
endif
endif
LDFLAGS
+=
$(LIBM)
CORE_DIR
:=
.
CORE_DIR
:=
.
ifneq
($(VORBISLIB),vorbis)
ifneq
($(VORBISLIB),tremor)
$(error
Invalid
VORBISLIB
setting)
endif
endif
ifneq
($(MP3LIB),mpg123)
ifneq
($(MP3LIB),mad)
$(error
Invalid
MP3LIB
setting)
endif
endif
ifeq
($(MP3LIB),mad)
mp3_obj
=
snd_mp3.o
lib_mp3dec
=
-lmad
endif
ifeq
($(MP3LIB),mpg123)
mp3_obj
=
snd_mpg123.o
lib_mp3dec
=
-lmpg123
endif
ifeq
($(VORBISLIB),vorbis)
cpp_vorbisdec
=
lib_vorbisdec
=
-lvorbisfile
-lvorbis
-logg
endif
ifeq
($(VORBISLIB),tremor)
cpp_vorbisdec
=
-DVORBIS_USE_TREMOR
lib_vorbisdec
=
-lvorbisidec
-logg
endif
CODECLIBS
:=
ifeq
($(USE_CODEC_WAVE),1)
CFLAGS
+=
-DUSE_CODEC_WAVE
endif
ifeq
($(USE_CODEC_FLAC),1)
CFLAGS
+=
-DUSE_CODEC_FLAC
CODECLIBS
+=
-lFLAC
endif
ifeq
($(USE_CODEC_OPUS),1)
# opus and opusfile put their *.h under <includedir>/opus,
# but they include the headers without the opus directory
# prefix and rely on pkg-config. ewww...
CFLAGS
+=
-DUSE_CODEC_OPUS
CFLAGS
+=
$(
shell
pkg-config
--cflags
opusfile
)
CODECLIBS
+=
$(
shell
pkg-config
--libs
opusfile
)
endif
ifeq
($(USE_CODEC_VORBIS),1)
CFLAGS
+=
-DUSE_CODEC_VORBIS
$(cpp_vorbisdec)
CODECLIBS
+=
$(lib_vorbisdec)
endif
ifeq
($(USE_CODEC_MP3),1)
CFLAGS
+=
-DUSE_CODEC_MP3
CODECLIBS
+=
$(lib_mp3dec)
endif
ifeq
($(USE_CODEC_MIKMOD),1)
CFLAGS
+=
-DUSE_CODEC_MIKMOD
CODECLIBS
+=
-lmikmod
endif
ifeq
($(USE_CODEC_MODPLUG),1)
CFLAGS
+=
-DUSE_CODEC_MODPLUG
CODECLIBS
+=
-lmodplug
endif
ifeq
($(USE_CODEC_UMX),1)
CFLAGS
+=
-DUSE_CODEC_UMX
endif
LDFLAGS
+=
$(CODECLIBS)
include
Makefile.common
include
Makefile.common
OBJECTS
=
$(SOURCES_C:.c=.o)
OBJECTS
=
$(SOURCES_C:.c=.o)
...
...
Makefile.common
View file @
93468f1b
...
@@ -62,6 +62,16 @@ SOURCES_C := \
...
@@ -62,6 +62,16 @@ SOURCES_C := \
$(CORE_DIR)
/common/screen.c
\
$(CORE_DIR)
/common/screen.c
\
$(CORE_DIR)
/common/shell.c
\
$(CORE_DIR)
/common/shell.c
\
$(CORE_DIR)
/common/bgmusic.c
\
$(CORE_DIR)
/common/bgmusic.c
\
$(CORE_DIR)
/common/snd_codec.c
\
$(CORE_DIR)
/common/snd_flac.c
\
$(CORE_DIR)
/common/snd_mikmod.c
\
$(CORE_DIR)
/common/snd_modplug.c
\
$(CORE_DIR)
/common/snd_mp3.c
\
$(CORE_DIR)
/common/snd_mpg123.c
\
$(CORE_DIR)
/common/snd_opus.c
\
$(CORE_DIR)
/common/snd_umx.c
\
$(CORE_DIR)
/common/snd_vorbis.c
\
$(CORE_DIR)
/common/snd_wave.c
\
$(CORE_DIR)
/common/snd_dma.c
\
$(CORE_DIR)
/common/snd_dma.c
\
$(CORE_DIR)
/common/snd_mem.c
\
$(CORE_DIR)
/common/snd_mem.c
\
$(CORE_DIR)
/common/snd_mix.c
\
$(CORE_DIR)
/common/snd_mix.c
\
...
...
common/bgmusic.c
View file @
93468f1b
/*
* 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-2012 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
*
*/
#include "quakedef.h"
#include "quakedef.h"
#include "console.h"
#include "console.h"
#include "common.h"
#include "common.h"
...
@@ -5,31 +29,431 @@
...
@@ -5,31 +29,431 @@
#include "sound.h"
#include "sound.h"
#include "cdaudio.h"
#include "cdaudio.h"
#include "snd_codec.h"
#include "bgmusic.h"
#include "bgmusic.h"
qboolean
BGM_Init
(
void
)
{
#define MUSIC_DIRNAME "music"
qboolean
bgmloop
;
cvar_t
bgm_extmusic
=
{
"bgm_extmusic"
,
"1"
,
false
};
static
qboolean
no_extmusic
=
false
;
static
float
old_volume
=
-
1
.
0
f
;
typedef
enum
_bgm_player
{
BGM_NONE
=
-
1
,
BGM_MIDIDRV
=
1
,
BGM_STREAMER
}
bgm_player_t
;
typedef
struct
music_handler_s
{
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
}
};
static
music_handler_t
*
music_handlers
=
NULL
;
#define ANY_CODECTYPE 0xFFFFFFFF
#define CDRIP_TYPES (CODECTYPE_VORBIS | CODECTYPE_MP3 | CODECTYPE_FLAC | CODECTYPE_WAV)
#define CDRIPTYPE(x) (((x) & CDRIP_TYPES) != 0)
static
snd_stream_t
*
bgmstream
=
NULL
;
static
void
BGM_Play_f
(
void
)
{
if
(
Cmd_Argc
()
==
2
)
{
BGM_Play
(
Cmd_Argv
(
1
));
}
else
{
Con_Printf
(
"music <musicfile>
\n
"
);
return
;
return
;
}
}
}
void
BGM_Shutdown
(
void
)
{
return
;
static
void
BGM_Pause_f
(
void
)
{
BGM_Pause
();
}
}
void
BGM_Play
(
const
char
*
filename
)
{
static
void
BGM_Resume_f
(
void
)
return
;
{
BGM_Resume
();
}
}
void
BGM_Stop
(
void
)
{
return
;
static
void
BGM_Loop_f
(
void
)
{
if
(
Cmd_Argc
()
==
2
)
{
if
(
strcasecmp
(
Cmd_Argv
(
1
),
"0"
)
==
0
||
strcasecmp
(
Cmd_Argv
(
1
),
"off"
)
==
0
)
bgmloop
=
false
;
else
if
(
strcasecmp
(
Cmd_Argv
(
1
),
"1"
)
==
0
||
strcasecmp
(
Cmd_Argv
(
1
),
"on"
)
==
0
)
bgmloop
=
true
;
else
if
(
strcasecmp
(
Cmd_Argv
(
1
),
"toggle"
)
==
0
)
bgmloop
=
!
bgmloop
;
}
if
(
bgmloop
)
Con_Printf
(
"Music will be looped
\n
"
);
else
Con_Printf
(
"Music will not be looped
\n
"
);
}
}
void
BGM_Update
(
void
)
{
return
;
static
void
BGM_Stop_f
(
void
)
{
BGM_Stop
();
}
}
void
BGM_Pause
(
void
)
{
qboolean
BGM_Init
(
void
)
{
music_handler_t
*
handlers
=
NULL
;
int
i
;
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
);
if
(
COM_CheckParm
(
"-noextmusic"
)
!=
0
)
no_extmusic
=
true
;
bgmloop
=
true
;
for
(
i
=
0
;
wanted_handlers
[
i
].
type
!=
CODECTYPE_NONE
;
i
++
)
{
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
;
}
}
}
return
true
;
}
void
BGM_Shutdown
(
void
)
{
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
)
{
char
tmp
[
MAX_QPATH
];
music_handler_t
*
handler
;
handler
=
music_handlers
;
while
(
handler
)
{
if
(
!
(
handler
->
type
&
allowed_types
))
{
handler
=
handler
->
next
;
continue
;
}
if
(
!
handler
->
is_available
)
{
handler
=
handler
->
next
;
continue
;
}
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
;
}
Con_Printf
(
"Couldn't handle music file %s
\n
"
,
filename
);
}
void
BGM_Play
(
const
char
*
filename
)
{
char
tmp
[
MAX_QPATH
];
const
char
*
ext
;
music_handler_t
*
handler
;
BGM_Stop
();
if
(
music_handlers
==
NULL
)
return
;
return
;
if
(
!
filename
||
!*
filename
)
{
Con_DPrintf
(
"null music file name
\n
"
);
return
;
}
ext
=
COM_FileExtension
(
filename
);
if
(
!
*
ext
)
/* try all things */
{
BGM_Play_noext
(
filename
,
ANY_CODECTYPE
);
return
;
}
handler
=
music_handlers
;
while
(
handler
)
{
if
(
handler
->
is_available
&&
!
strcasecmp
(
ext
,
handler
->
ext
))
break
;
handler
=
handler
->
next
;
}
if
(
!
handler
)
{
Con_Printf
(
"Unhandled extension for %s
\n
"
,
filename
);
return
;
}
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
);
}
}
void
BGM_Resume
(
void
)
{
void
BGM_PlayCDtrack
(
byte
track
,
qboolean
looping
)
{
/* 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.
*/
char
tmp
[
MAX_QPATH
];
const
char
*
ext
;
unsigned
int
type
;
music_handler_t
*
handler
;
BGM_Stop
();
if
(
CDAudio_Play
(
track
,
looping
)
==
0
)
return
;
/* success */
if
(
music_handlers
==
NULL
)
return
;
if
(
no_extmusic
||
!
bgm_extmusic
.
value
)
return
;
return
;
type
=
0
;
ext
=
NULL
;
handler
=
music_handlers
;
while
(
handler
)
{
if
(
!
handler
->
is_available
)
goto
_next
;
if
(
!
CDRIPTYPE
(
handler
->
type
))
goto
_next
;
snprintf
(
tmp
,
sizeof
(
tmp
),
"%s/track%02d.%s"
,
MUSIC_DIRNAME
,
(
int
)
track
,
handler
->
ext
);
if
(
!
COM_FileExists
(
tmp
))
goto
_next
;
type
=
handler
->
type
;
ext
=
handler
->
ext
;
_next:
handler
=
handler
->
next
;
}
if
(
ext
==
NULL
)
Con_Printf
(
"Couldn't find a cdrip for track %d
\n
"
,
(
int
)
track
);
else
{
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
);
}
}
void
BGM_Stop
(
void
)
{
if
(
bgmstream
)
{
bgmstream
->
status
=
STREAM_NONE
;
S_CodecCloseStream
(
bgmstream
);
bgmstream
=
NULL
;
s_rawend
=
0
;
}
}
void
BGM_Pause
(
void
)
{
if
(
bgmstream
)
{
if
(
bgmstream
->
status
==
STREAM_PLAY
)
bgmstream
->
status
=
STREAM_PAUSE
;
}
}
void
BGM_Resume
(
void
)
{
if
(
bgmstream
)
{
if
(
bgmstream
->
status
==
STREAM_PAUSE
)
bgmstream
->
status
=
STREAM_PLAY
;
}
}
}
void
BGM_PlayCDtrack
(
byte
track
,
qboolean
looping
)
{
static
void
BGM_UpdateStream
(
void
)
{
int
res
;
/* Number of bytes read. */
int
bufferSamples
;
int
fileSamples
;
int
fileBytes
;
byte
raw
[
16384
];
if
(
bgmstream
->
status
!=
STREAM_PLAY
)
return
;
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
)
{
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
);
}
else
if
(
res
==
0
)
/* EOF */
{
if
(
bgmloop
)
{
res
=
S_CodecRewindStream
(
bgmstream
);
if
(
res
!=
0
)
{
Con_Printf
(
"Stream seek error (%i), stopping.
\n
"
,
res
);
BGM_Stop
();
return
;
}
}
else
{
BGM_Stop
();
return
;
}
}
else
/* res < 0: some read error */
{
Con_Printf
(
"Stream read error (%i), stopping.
\n
"
,
res
);
BGM_Stop
();
return
;
}
}
}
void
BGM_Update
(
void
)
{
if
(
old_volume
!=
bgmvolume
.
value
)
{
if
(
bgmvolume
.
value
<
0
)
Cvar_Set
(
"bgmvolume"
,
"0"
);
else
if
(
bgmvolume
.
value
>
1
)
Cvar_Set
(
"bgmvolume"
,
"1"
);
old_volume
=
bgmvolume
.
value
;
}
if
(
bgmstream
)
BGM_UpdateStream
();
}
}
common/snd_codec.c
0 → 100644
View file @
93468f1b
/*
* Audio Codecs: Adapted from ioquake3 with changes.
* For now, only handles streaming music, not sound effects.
*
* Copyright (C) 1999-2005 Id Software, Inc.
* Copyright (C) 2005 Stuart Dalton <badcdev@gmail.com>
* Copyright (C) 2010-2012 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
*
*/