Merge several FS_* and snd_codec* layer updates from uhexen2 tree:

tidy-ups in FS* stdio replacement functions. add new FS_filelength.
snd codec layer updates: changed codec_open() to operate only on a
stream pointer and moved all file open/close stuff to snd_codec.c.
codec_open now only returns true or false upon success or failure
instead of a stream pointer. added new snd_codec.c toplevel helper
S_CodecForwardStream(), which allows one codec to hand over its
stream from its codec_open() to another codec. Support for tracker
(mod) music, including support for Unreal umx containers. (might
be useful if we ever make a Nehahra version of the engine some day.
edit the makefiles to enable when compiling.)


git-svn-id: svn+ssh://svn.code.sf.net/p/quakespasm/code/trunk@867 af15c1b1-3010-417e-b628-4374ebc0bcbd
This commit is contained in:
sezero 2013-09-25 11:01:12 +00:00
parent b5b1bc07e1
commit 32d841af26
22 changed files with 971 additions and 130 deletions

View file

@ -14,6 +14,10 @@ USE_CODEC_FLAC=0
USE_CODEC_MP3=1
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
@ -157,6 +161,17 @@ 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
COMMON_LIBS:= -lm -lGL
@ -187,7 +202,10 @@ MUSIC_OBJS:= bgmusic.o \
snd_wave.o \
snd_vorbis.o \
snd_opus.o \
$(mp3_obj)
$(mp3_obj) \
snd_mikmod.o \
snd_modplug.o \
snd_umx.o
COMOBJ_SND := snd_dma.o snd_mix.o snd_mem.o $(MUSIC_OBJS)
SYSOBJ_SND := snd_sdl.o
SYSOBJ_CDA := cd_sdl.o

View file

@ -15,6 +15,10 @@ USE_CODEC_FLAC=1
USE_CODEC_MP3=1
USE_CODEC_VORBIS=1
USE_CODEC_OPUS=1
# 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
@ -149,6 +153,21 @@ CODEC_INC = -I../MacOSX/codecs/include
CODEC_LINK= -L../MacOSX/codecs/lib
CODECLIBS+= $(lib_mp3dec)
endif
ifeq ($(USE_CODEC_MIKMOD),1)
CFLAGS+= -DUSE_CODEC_MIKMOD
CODEC_INC = -I../MacOSX/codecs/include
CODEC_LINK= -L../MacOSX/codecs/lib
CODECLIBS+= -lmikmod
endif
ifeq ($(USE_CODEC_MODPLUG),1)
CFLAGS+= -DUSE_CODEC_MODPLUG
CODEC_INC = -I../MacOSX/codecs/include
CODEC_LINK= -L../MacOSX/codecs/lib
CODECLIBS+= -lmodplug
endif
ifeq ($(USE_CODEC_UMX),1)
CFLAGS+= -DUSE_CODEC_UMX
endif
CFLAGS+= $(CODEC_INC)
COMMON_LIBS:= -Wl,-framework,IOKit -Wl,-framework,OpenGL
@ -184,7 +203,10 @@ MUSIC_OBJS:= bgmusic.o \
snd_wave.o \
snd_vorbis.o \
snd_opus.o \
$(mp3_obj)
$(mp3_obj) \
snd_mikmod.o \
snd_modplug.o \
snd_umx.o
COMOBJ_SND := snd_dma.o snd_mix.o snd_mem.o $(MUSIC_OBJS)
SYSOBJ_SND := snd_sdl.o
SYSOBJ_CDA := cd_sdl.o

View file

@ -15,6 +15,10 @@ USE_CODEC_FLAC=0
USE_CODEC_MP3=1
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
@ -155,6 +159,21 @@ CODEC_INC = -I../Windows/codecs/include
CODEC_LINK= -L../Windows/codecs/x86
CODECLIBS+= $(lib_mp3dec)
endif
ifeq ($(USE_CODEC_MIKMOD),1)
CFLAGS+= -DUSE_CODEC_MIKMOD
CODEC_INC = -I../Windows/codecs/include
CODEC_LINK= -L../Windows/codecs/x86
CODECLIBS+= -lmikmod
endif
ifeq ($(USE_CODEC_MODPLUG),1)
CFLAGS+= -DUSE_CODEC_MODPLUG
CODEC_INC = -I../Windows/codecs/include
CODEC_LINK= -L../Windows/codecs/x86
CODECLIBS+= -lmodplug
endif
ifeq ($(USE_CODEC_UMX),1)
CFLAGS+= -DUSE_CODEC_UMX
endif
CFLAGS+= $(CODEC_INC)
COMMON_LIBS:= -lm -lopengl32
@ -188,7 +207,10 @@ MUSIC_OBJS:= bgmusic.o \
snd_wave.o \
snd_vorbis.o \
snd_opus.o \
$(mp3_obj)
$(mp3_obj) \
snd_mikmod.o \
snd_modplug.o \
snd_umx.o
COMOBJ_SND := snd_dma.o snd_mix.o snd_mem.o $(MUSIC_OBJS)
SYSOBJ_SND := snd_sdl.o
SYSOBJ_CDA := cd_sdl.o

View file

@ -15,6 +15,10 @@ USE_CODEC_FLAC=0
USE_CODEC_MP3=1
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
@ -155,6 +159,21 @@ CODEC_INC = -I../Windows/codecs/include
CODEC_LINK= -L../Windows/codecs/x64
CODECLIBS+= $(lib_mp3dec)
endif
ifeq ($(USE_CODEC_MIKMOD),1)
CFLAGS+= -DUSE_CODEC_MIKMOD
CODEC_INC = -I../Windows/codecs/include
CODEC_LINK= -L../Windows/codecs/x64
CODECLIBS+= -lmikmod
endif
ifeq ($(USE_CODEC_MODPLUG),1)
CFLAGS+= -DUSE_CODEC_MODPLUG
CODEC_INC = -I../Windows/codecs/include
CODEC_LINK= -L../Windows/codecs/x64
CODECLIBS+= -lmodplug
endif
ifeq ($(USE_CODEC_UMX),1)
CFLAGS+= -DUSE_CODEC_UMX
endif
CFLAGS+= $(CODEC_INC)
COMMON_LIBS:= -lm -lopengl32
@ -188,7 +207,10 @@ MUSIC_OBJS:= bgmusic.o \
snd_wave.o \
snd_vorbis.o \
snd_opus.o \
$(mp3_obj)
$(mp3_obj) \
snd_mikmod.o \
snd_modplug.o \
snd_umx.o
COMOBJ_SND := snd_dma.o snd_mix.o snd_mem.o $(MUSIC_OBJS)
SYSOBJ_SND := snd_sdl.o
SYSOBJ_CDA := cd_sdl.o

View file

@ -58,6 +58,11 @@ static music_handler_t wanted_handlers[] =
{ 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 }
};

View file

@ -2008,24 +2008,19 @@ size_t FS_fread(void *ptr, size_t size, size_t nmemb, fshandle_t *fh)
long bytes_read;
size_t nmemb_read;
if (!ptr)
{
if (!fh) {
errno = EBADF;
return 0;
}
if (!ptr) {
errno = EFAULT;
return 0;
}
if (!(size && nmemb)) /* not an error, just zero bytes wanted */
{
if (!size || !nmemb) { /* no error, just zero bytes wanted */
errno = 0;
return 0;
}
if (!fh)
{
errno = EBADF;
return 0;
}
byte_size = nmemb * size;
if (byte_size > fh->length - fh->pos) /* just read to end */
byte_size = fh->length - fh->pos;
@ -2049,8 +2044,7 @@ int FS_fseek(fshandle_t *fh, long offset, int whence)
* the quake/hexen2 file system is 32 bits, anyway. */
int ret;
if (!fh)
{
if (!fh) {
errno = EBADF;
return -1;
}
@ -2072,8 +2066,7 @@ int FS_fseek(fshandle_t *fh, long offset, int whence)
return -1;
}
if (offset < 0)
{
if (offset < 0) {
errno = EINVAL;
return -1;
}
@ -2091,32 +2084,25 @@ int FS_fseek(fshandle_t *fh, long offset, int whence)
int FS_fclose(fshandle_t *fh)
{
if (!fh)
{
if (!fh) {
errno = EBADF;
return -1;
}
return fclose(fh->file);
}
long FS_ftell(fshandle_t *fh)
{
if (!fh)
{
if (!fh) {
errno = EBADF;
return -1;
}
/* send the relative file position */
return fh->pos;
}
void FS_rewind(fshandle_t *fh)
{
if (!fh)
return;
if (!fh) return;
clearerr(fh->file);
fseek(fh->file, fh->start, SEEK_SET);
fh->pos = 0;
@ -2124,6 +2110,10 @@ void FS_rewind(fshandle_t *fh)
int FS_feof(fshandle_t *fh)
{
if (!fh) {
errno = EBADF;
return -1;
}
if (fh->pos >= fh->length)
return -1;
return 0;
@ -2131,6 +2121,10 @@ int FS_feof(fshandle_t *fh)
int FS_ferror(fshandle_t *fh)
{
if (!fh) {
errno = EBADF;
return -1;
}
return ferror(fh->file);
}
@ -2150,3 +2144,12 @@ char *FS_fgets(char *s, int size, fshandle_t *fh)
return ret;
}
long FS_filelength (fshandle_t *fh)
{
if (!fh) {
errno = EBADF;
return -1;
}
return fh->length;
}

View file

@ -249,6 +249,7 @@ int FS_feof(fshandle_t *fh);
int FS_ferror(fshandle_t *fh);
int FS_fclose(fshandle_t *fh);
char *FS_fgets(char *s, int size, fshandle_t *fh);
long FS_filelength (fshandle_t *fh);
extern struct cvar_s registered;

View file

@ -28,6 +28,9 @@
#include "snd_codeci.h"
/* headers for individual codecs */
#include "snd_mikmod.h"
#include "snd_modplug.h"
#include "snd_umx.h"
#include "snd_wave.h"
#include "snd_flac.h"
#include "snd_mp3.h"
@ -60,6 +63,15 @@ void S_CodecInit (void)
/* Register in the inverse order
* of codec choice preference: */
#ifdef USE_CODEC_UMX
S_CodecRegister(&umx_codec);
#endif
#ifdef USE_CODEC_MODPLUG
S_CodecRegister(&modplug_codec);
#endif
#ifdef USE_CODEC_MIKMOD
S_CodecRegister(&mikmod_codec);
#endif
#ifdef USE_CODEC_WAVE
S_CodecRegister(&wav_codec);
#endif
@ -75,6 +87,7 @@ void S_CodecInit (void)
#ifdef USE_CODEC_OPUS
S_CodecRegister(&opus_codec);
#endif
codec = codecs;
while (codec)
{
@ -127,9 +140,12 @@ snd_stream_t *S_CodecOpenStreamType (const char *filename, unsigned int type)
Con_Printf("Unknown type for %s\n", filename);
return NULL;
}
stream = codec->codec_open(filename);
if (stream)
stream->status = STREAM_PLAY;
stream = S_CodecUtilOpen(filename, codec);
if (stream) {
if (codec->codec_open(stream))
stream->status = STREAM_PLAY;
else S_CodecUtilClose(&stream);
}
return stream;
}
@ -158,9 +174,12 @@ snd_stream_t *S_CodecOpenStreamExt (const char *filename)
Con_Printf("Unknown extension for %s\n", filename);
return NULL;
}
stream = codec->codec_open(filename);
if (stream)
stream->status = STREAM_PLAY;
stream = S_CodecUtilOpen(filename, codec);
if (stream) {
if (codec->codec_open(stream))
stream->status = STREAM_PLAY;
else S_CodecUtilClose(&stream);
}
return stream;
}
@ -179,11 +198,13 @@ snd_stream_t *S_CodecOpenStreamAny (const char *filename)
while (codec)
{
q_snprintf(tmp, sizeof(tmp), "%s.%s", filename, codec->ext);
stream = codec->codec_open(tmp);
if (stream)
{
stream->status = STREAM_PLAY;
return stream;
stream = S_CodecUtilOpen(tmp, codec);
if (stream) {
if (codec->codec_open(stream)) {
stream->status = STREAM_PLAY;
return stream;
}
S_CodecUtilClose(&stream);
}
codec = codec->next;
}
@ -204,13 +225,31 @@ snd_stream_t *S_CodecOpenStreamAny (const char *filename)
Con_Printf("Unknown extension for %s\n", filename);
return NULL;
}
stream = codec->codec_open(filename);
if (stream)
stream->status = STREAM_PLAY;
stream = S_CodecUtilOpen(filename, codec);
if (stream) {
if (codec->codec_open(stream))
stream->status = STREAM_PLAY;
else S_CodecUtilClose(&stream);
}
return stream;
}
}
qboolean S_CodecForwardStream (snd_stream_t *stream, unsigned int type)
{
snd_codec_t *codec = codecs;
while (codec)
{
if (type == codec->type)
break;
codec = codec->next;
}
if (!codec) return false;
stream->codec = codec;
return codec->codec_open(stream);
}
void S_CodecCloseStream (snd_stream_t *stream)
{
stream->status = STREAM_NONE;
@ -253,6 +292,8 @@ snd_stream_t *S_CodecUtilOpen(const char *filename, snd_codec_t *codec)
stream->fh.pos = 0;
stream->fh.length = length;
stream->fh.pak = stream->pak = pak;
q_strlcpy(stream->name, filename, MAX_QPATH);
return stream;
}

View file

@ -50,6 +50,7 @@ typedef struct snd_stream_s
{
fshandle_t fh;
qboolean pak;
char name[MAX_QPATH]; /* name of the source file */
snd_info_t info;
stream_status_t status;
snd_codec_t *codec; /* codec handling this stream */
@ -90,6 +91,7 @@ void S_CodecUtilClose(snd_stream_t **stream);
#define CODECTYPE_MP3 (1U << 4)
#define CODECTYPE_VORBIS (1U << 5)
#define CODECTYPE_OPUS (1U << 6)
#define CODECTYPE_UMX (1U << 7)
#define CODECTYPE_WAVE CODECTYPE_WAV
#define CODECTYPE_MIDI CODECTYPE_MID

View file

@ -29,7 +29,7 @@
/* Codec internals */
typedef qboolean (*CODEC_INIT)(void);
typedef void (*CODEC_SHUTDOWN)(void);
typedef snd_stream_t *(*CODEC_OPEN)(const char *filename);
typedef qboolean (*CODEC_OPEN)(snd_stream_t *stream);
typedef int (*CODEC_READ)(snd_stream_t *stream, int bytes, void *buffer);
typedef int (*CODEC_REWIND)(snd_stream_t *stream);
typedef void (*CODEC_CLOSE)(snd_stream_t *stream);
@ -48,5 +48,8 @@ struct snd_codec_s
snd_codec_t *next;
};
qboolean S_CodecForwardStream (snd_stream_t *stream, unsigned int type);
/* Forward a stream to another codec of 'type' type. */
#endif /* _SND_CODECI_H_ */

View file

@ -126,7 +126,7 @@ flac_length_func (const FLAC__StreamDecoder *decoder,
FLAC__uint64 *stream_length, void *client_data)
{
flacfile_t *ff = (flacfile_t *) client_data;
*stream_length = (FLAC__uint64) ff->file->length;
*stream_length = (FLAC__uint64) FS_filelength (ff->file);
return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
}
@ -235,16 +235,11 @@ static void S_FLAC_CodecShutdown (void)
{
}
static snd_stream_t *S_FLAC_CodecOpenStream (const char *filename)
static qboolean S_FLAC_CodecOpenStream (snd_stream_t *stream)
{
snd_stream_t *stream;
flacfile_t *ff;
int rc;
stream = S_CodecUtilOpen(filename, &flac_codec);
if (!stream)
return NULL;
ff = (flacfile_t *) Z_Malloc(sizeof(flacfile_t));
ff->decoder = FLAC__stream_decoder_new ();
@ -293,28 +288,29 @@ static snd_stream_t *S_FLAC_CodecOpenStream (const char *filename)
{
rc = FLAC__stream_decoder_get_state(ff->decoder);
Con_Printf("%s not a valid flac file? (decoder state %i)\n",
filename, rc);
stream->name, rc);
goto _fail;
}
if (ff->info->dataofs < 0)
{
Con_Printf("%s has no STREAMINFO\n", filename);
Con_Printf("%s has no STREAMINFO\n", stream->name);
goto _fail;
}
if (ff->info->bits != 8 && ff->info->bits != 16)
{
Con_Printf("%s is not 8 or 16 bit\n", filename);
Con_Printf("%s is not 8 or 16 bit\n", stream->name);
goto _fail;
}
if (ff->info->channels != 1 && ff->info->channels != 2)
{
Con_Printf("Unsupported number of channels %d in %s\n",
ff->info->channels, filename);
ff->info->channels, stream->name);
goto _fail;
}
return stream;
return true;
_fail:
if (ff->decoder)
{
@ -322,8 +318,7 @@ _fail:
FLAC__stream_decoder_delete (ff->decoder);
}
Z_Free(ff);
S_CodecUtilClose(&stream);
return NULL;
return false;
}
static int S_FLAC_CodecReadStream (snd_stream_t *stream, int len, void *buffer)

View file

@ -0,0 +1,199 @@
/*
* tracker music (module file) decoding support using libmikmod
*
* Copyright (C) 2013 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"
#if defined(USE_CODEC_MIKMOD)
#include "snd_codec.h"
#include "snd_codeci.h"
#include "snd_mikmod.h"
#include <mikmod.h>
#ifndef DMODE_SIMDMIXER
#define DMODE_SIMDMIXER 0x0800 /* enable SIMD mixing */
#endif
typedef struct _mik_priv {
/* struct MREADER in libmikmod <= 3.2.0-beta2
* doesn't have iobase members. adding them here
* so that if we compile against 3.2.0-beta2, we
* can still run OK against 3.2.0b3 and newer. */
struct MREADER reader;
long iobase, prev_iobase;
fshandle_t *fh;
MODULE *module;
} mik_priv_t;
static BOOL MIK_Seek (MREADER *r, long ofs, int whence)
{
return FS_fseek (((mik_priv_t *)r)->fh, ofs, whence);
}
static long MIK_Tell (MREADER *r)
{
return FS_ftell (((mik_priv_t *)r)->fh);
}
static BOOL MIK_Read (MREADER *r, void *ptr, size_t siz)
{
return !!FS_fread(ptr, siz, 1, ((mik_priv_t *)r)->fh);
}
static int MIK_Get (MREADER *r)
{
unsigned char c;
if (FS_feof(((mik_priv_t *)r)->fh))
return EOF;
if (FS_fread(&c, 1, 1, ((mik_priv_t *)r)->fh))
return (int)c;
return EOF;
}
static BOOL MIK_Eof (MREADER *r)
{
return FS_feof(((mik_priv_t *)r)->fh);
}
static qboolean S_MIKMOD_CodecInitialize (void)
{
if (mikmod_codec.initialized)
return true;
/* set mode flags to only we like: */
md_mode = 0;
if ((shm->samplebits / 8) == 2)
md_mode |= DMODE_16BITS;
if (shm->channels == 2)
md_mode |= DMODE_STEREO;
md_mode |= DMODE_SOFT_MUSIC; /* this is a software-only mixer */
md_mode |= DMODE_HQMIXER; /* high-quality mixer is OK */
/* md_mixfreq is UWORD, so something like 96000 isn't OK */
md_mixfreq = (shm->speed < 65536)? shm->speed : 48000;
/* keeping md_device as 0 which is default (auto-detect: we
* only register drv_nos, and it will be the only one found.)
* md_pansep (stereo channels separation) default 128 is OK.
* no reverbation (md_reverb 0 (up to 15)) is OK.
* md_musicvolume and md_sndfxvolume defaults are 128: OK.
* just tone down overall volume md_volume from 128 to 96: */
md_volume = 96;
MikMod_RegisterDriver(&drv_nos);
MikMod_RegisterAllLoaders();
if (MikMod_Init(NULL))
{
Con_DPrintf("Could not initialize MikMod: %s\n", MikMod_strerror(MikMod_errno));
return false;
}
/* this can't get set with drv_nos, but whatever, be safe: */
md_mode &= ~DMODE_SIMDMIXER; /* SIMD mixer is buggy when combined with HQMIXER */
mikmod_codec.initialized = true;
return true;
}
static void S_MIKMOD_CodecShutdown (void)
{
if (mikmod_codec.initialized)
{
mikmod_codec.initialized = false;
MikMod_Exit();
}
}
static qboolean S_MIKMOD_CodecOpenStream (snd_stream_t *stream)
{
mik_priv_t *priv;
stream->priv = Z_Malloc(sizeof(mik_priv_t));
priv = (mik_priv_t *) stream->priv;
priv->reader.Seek = MIK_Seek;
priv->reader.Tell = MIK_Tell;
priv->reader.Read = MIK_Read;
priv->reader.Get = MIK_Get;
priv->reader.Eof = MIK_Eof;
priv->fh = &stream->fh;
priv->module = Player_LoadGeneric((MREADER *)stream->priv, 64, 0);
if (!priv->module)
{
Con_DPrintf("Could not load module: %s\n", MikMod_strerror(MikMod_errno));
Z_Free(stream->priv);
return false;
}
/* keep default values of fadeout (0: don't fade out volume during when last
* position of the module is being played), extspd (1: do process Protracker
* extended speed effect), panflag (1: do process panning effects), wrap (0:
* don't wrap to restart position when module is finished) are OK with us as
* set internally by libmikmod::Player_Init(). just change the loop setting
* to 0, i.e. don't process in-module loops: */
priv->module->loop = 0;
Player_Start(priv->module);
stream->info.rate = md_mixfreq;
stream->info.bits = (md_mode & DMODE_16BITS)? 16: 8;
stream->info.width = stream->info.bits / 8;
stream->info.channels = (md_mode & DMODE_STEREO)? 2 : 1;
/* Con_DPrintf("Playing %s (%d chn)\n", priv->module->songname, priv->module->numchn);*/
return true;
}
static int S_MIKMOD_CodecReadStream (snd_stream_t *stream, int bytes, void *buffer)
{
if (!Player_Active())
return 0;
return (int) VC_WriteBytes((SBYTE *)buffer, bytes);
}
static void S_MIKMOD_CodecCloseStream (snd_stream_t *stream)
{
Player_Stop();
Player_Free(((mik_priv_t *)stream->priv)->module);
Z_Free(stream->priv);
S_CodecUtilClose(&stream);
}
static int S_MIKMOD_CodecRewindStream (snd_stream_t *stream)
{
Player_SetPosition (0);
return 0;
}
snd_codec_t mikmod_codec =
{
CODECTYPE_MOD,
false,
"s3m",
S_MIKMOD_CodecInitialize,
S_MIKMOD_CodecShutdown,
S_MIKMOD_CodecOpenStream,
S_MIKMOD_CodecReadStream,
S_MIKMOD_CodecRewindStream,
S_MIKMOD_CodecCloseStream,
NULL
};
#endif /* USE_CODEC_MIKMOD */

View file

@ -0,0 +1,13 @@
/* module tracker decoding support using libmikmod */
#if !defined(_SND_MIKMOD_H_)
#define _SND_MIKMOD_H_
#if defined(USE_CODEC_MIKMOD)
extern snd_codec_t mikmod_codec;
#endif /* USE_CODEC_MIKMOD */
#endif /* ! _SND_MIKMOD_H_ */

View file

@ -0,0 +1,121 @@
/*
* tracker music (module file) decoding support using libmodplug
*
* Copyright (C) 2013 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"
#if defined(USE_CODEC_MODPLUG)
#include "snd_codec.h"
#include "snd_codeci.h"
#include "snd_modplug.h"
#include <libmodplug/modplug.h>
static void S_MODPLUG_SetSettings (snd_stream_t *stream)
{
ModPlug_Settings settings;
ModPlug_GetSettings(&settings);
settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING;
settings.mChannels = shm->channels;
settings.mBits = shm->samplebits;
settings.mFrequency = shm->speed;
settings.mResamplingMode = MODPLUG_RESAMPLE_SPLINE;/*MODPLUG_RESAMPLE_FIR*/
settings.mLoopCount = 0;
ModPlug_SetSettings(&settings);
if (stream) {
stream->info.rate = shm->speed;
stream->info.bits = shm->samplebits;
stream->info.width = stream->info.bits / 8;
stream->info.channels = shm->channels;
}
}
static qboolean S_MODPLUG_CodecInitialize (void)
{
return true;
}
static void S_MODPLUG_CodecShutdown (void)
{
}
static qboolean S_MODPLUG_CodecOpenStream (snd_stream_t *stream)
{
/* need to load the whole file into memory and pass it to libmodplug */
byte *moddata;
long len;
int mark;
len = FS_filelength (&stream->fh);
mark = Hunk_LowMark();
moddata = (byte *) Hunk_Alloc(len);
FS_fread(moddata, 1, len, &stream->fh);
S_MODPLUG_SetSettings(stream);
stream->priv = ModPlug_Load(moddata, len);
Hunk_FreeToLowMark(mark); /* free original file data */
if (!stream->priv)
{
Con_DPrintf("Could not load module %s\n", stream->name);
return false;
}
ModPlug_Seek((ModPlugFile*)stream->priv, 0);
#if 0
/* default volume (128) sounds rather low? */
ModPlug_SetMasterVolume((ModPlugFile*)stream->priv, 384); /* 0-512 */
#endif
return true;
}
static int S_MODPLUG_CodecReadStream (snd_stream_t *stream, int bytes, void *buffer)
{
return ModPlug_Read((ModPlugFile*)stream->priv, buffer, bytes);
}
static void S_MODPLUG_CodecCloseStream (snd_stream_t *stream)
{
ModPlug_Unload((ModPlugFile*)stream->priv);
S_CodecUtilClose(&stream);
}
static int S_MODPLUG_CodecRewindStream (snd_stream_t *stream)
{
ModPlug_Seek((ModPlugFile*)stream->priv, 0);
return 0;
}
snd_codec_t modplug_codec =
{
CODECTYPE_MOD,
true, /* always available. */
"s3m",
S_MODPLUG_CodecInitialize,
S_MODPLUG_CodecShutdown,
S_MODPLUG_CodecOpenStream,
S_MODPLUG_CodecReadStream,
S_MODPLUG_CodecRewindStream,
S_MODPLUG_CodecCloseStream,
NULL
};
#endif /* USE_CODEC_MODPLUG */

View file

@ -0,0 +1,12 @@
/* module tracker decoding support using libmodplug */
#if !defined(_SND_MODPLUG_H_)
#define _SND_MODPLUG_H_
#if defined(USE_CODEC_MODPLUG)
extern snd_codec_t modplug_codec;
#endif /* USE_CODEC_MODPLUG */
#endif /* ! _SND_MODPLUG_H_ */

View file

@ -491,49 +491,40 @@ static void S_MP3_CodecShutdown (void)
{
}
static snd_stream_t *S_MP3_CodecOpenStream (const char *filename)
static qboolean S_MP3_CodecOpenStream (snd_stream_t *stream)
{
snd_stream_t *stream;
int err;
stream = S_CodecUtilOpen(filename, &mp3_codec);
if (!stream)
return NULL;
#if 0 /*defined(CODECS_USE_ZONE)*/
stream->priv = Z_Malloc(sizeof(mp3_priv_t));
#else
stream->priv = calloc(1, sizeof(mp3_priv_t));
if (!stream->priv)
{
S_CodecUtilClose(&stream);
Con_Printf("Insufficient memory for MP3 audio\n");
return NULL;
return false;
}
#endif
err = mp3_startread(stream);
if (err != 0)
{
Con_Printf("%s is not a valid mp3 file\n", filename);
Con_Printf("%s is not a valid mp3 file\n", stream->name);
}
else if (stream->info.channels != 1 && stream->info.channels != 2)
{
Con_Printf("Unsupported number of channels %d in %s\n",
stream->info.channels, filename);
stream->info.channels, stream->name);
}
else
{
return stream;
return true;
}
#if 0 /*defined(CODECS_USE_ZONE)*/
Z_Free(stream->priv);
#else
free(stream->priv);
#endif
S_CodecUtilClose(&stream);
return NULL;
return false;
}
static int S_MP3_CodecReadStream (snd_stream_t *stream, int bytes, void *buffer)

View file

@ -86,17 +86,12 @@ static void S_MP3_CodecShutdown (void)
}
}
static snd_stream_t *S_MP3_CodecOpenStream (const char *filename)
static qboolean S_MP3_CodecOpenStream (snd_stream_t *stream)
{
snd_stream_t *stream;
long rate = 0;
int encoding = 0, channels = 0;
mp3_priv_t *priv = NULL;
stream = S_CodecUtilOpen(filename, &mp3_codec);
if (!stream)
return NULL;
stream->priv = Z_Malloc(sizeof(mp3_priv_t));
priv = (mp3_priv_t *) stream->priv;
priv->handle = mpg123_new(NULL, NULL);
@ -117,7 +112,7 @@ static snd_stream_t *S_MP3_CodecOpenStream (const char *filename)
if (mpg123_getformat(priv->handle, &rate, &channels, &encoding) != MPG123_OK)
{
Con_Printf("Unable to retrieve mpg123 format for %s\n", filename);
Con_Printf("Unable to retrieve mpg123 format for %s\n", stream->name);
goto _fail;
}
@ -130,7 +125,7 @@ static snd_stream_t *S_MP3_CodecOpenStream (const char *filename)
stream->info.channels = 2;
break;
default:
Con_Printf("Unsupported number of channels %d in %s\n", channels, filename);
Con_Printf("Unsupported number of channels %d in %s\n", channels, stream->name);
goto _fail;
}
@ -162,13 +157,13 @@ static snd_stream_t *S_MP3_CodecOpenStream (const char *filename)
}
if (mpg123_format_support(priv->handle, rate, encoding) == 0)
{
Con_Printf("Unsupported format for %s\n", filename);
Con_Printf("Unsupported format for %s\n", stream->name);
goto _fail;
}
mpg123_format_none(priv->handle);
mpg123_format(priv->handle, rate, channels, encoding);
return stream;
return true;
_fail:
if (priv)
{
@ -178,8 +173,7 @@ _fail:
mpg123_delete(priv->handle);
Z_Free(stream->priv);
}
S_CodecUtilClose(&stream);
return NULL;
return false;
}
static int S_MP3_CodecReadStream (snd_stream_t *stream, int bytes, void *buffer)

View file

@ -83,23 +83,18 @@ static void S_OPUS_CodecShutdown (void)
{
}
static snd_stream_t *S_OPUS_CodecOpenStream (const char *filename)
static qboolean S_OPUS_CodecOpenStream (snd_stream_t *stream)
{
snd_stream_t *stream;
OggOpusFile *opFile;
const OpusHead *op_info;
long numstreams;
int res;
stream = S_CodecUtilOpen(filename, &opus_codec);
if (!stream)
return NULL;
opFile = op_open_callbacks(&stream->fh, &opc_qfs, NULL, 0, &res);
if (!opFile)
{
Con_Printf("%s is not a valid Opus file (error %i).\n",
filename, res);
stream->name, res);
goto _fail;
}
@ -107,14 +102,14 @@ static snd_stream_t *S_OPUS_CodecOpenStream (const char *filename)
if (!op_seekable(opFile))
{
Con_Printf("Opus stream %s not seekable.\n", filename);
Con_Printf("Opus stream %s not seekable.\n", stream->name);
goto _fail;
}
op_info = op_head(opFile, -1);
if (!op_info)
{
Con_Printf("Unable to get stream information for %s.\n", filename);
Con_Printf("Unable to get stream information for %s.\n", stream->name);
goto _fail;
}
@ -123,14 +118,14 @@ static snd_stream_t *S_OPUS_CodecOpenStream (const char *filename)
if (numstreams != 1)
{
Con_Printf("More than one (%ld) stream in %s\n",
(long)op_info->stream_count, filename);
(long)op_info->stream_count, stream->name);
goto _fail;
}
if (op_info->channel_count != 1 && op_info->channel_count != 2)
{
Con_Printf("Unsupported number of channels %d in %s\n",
op_info->channel_count, filename);
op_info->channel_count, stream->name);
goto _fail;
}
@ -144,12 +139,11 @@ static snd_stream_t *S_OPUS_CodecOpenStream (const char *filename)
stream->info.bits = 16;
stream->info.width = 2;
return stream;
return true;
_fail:
if (opFile)
op_free(opFile);
S_CodecUtilClose(&stream);
return NULL;
return false;
}
static int S_OPUS_CodecReadStream (snd_stream_t *stream, int bytes, void *buffer)

387
quakespasm/Quake/snd_umx.c Normal file
View file

@ -0,0 +1,387 @@
/*
* Unreal UMX container support. UMX parsing is based on Unreal Media
* Ripper (UMR) v0.3 by Andy Ward <wardwh@swbell.net>, with additional
* updates by O. Sezer - see git repo at https://github.com/sezero/umr/
*
* Copyright (C) 2013 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"
#if defined(USE_CODEC_UMX)
#include "snd_codec.h"
#include "snd_codeci.h"
#include "snd_umx.h"
#define UPKG_HDR_TAG 0x9e2a83c1
#pragma pack(1)
struct upkg_hdr {
uint32_t tag; /* UPKG_HDR_TAG */
int32_t file_version, /* 61 for original unreal */
pkg_flags, /* bitflags - none needed */
name_count, /* number of names in name table (>= 0) */
name_offset, /* offset to name table (>= 0) */
export_count, /* num. exports in export table (>= 0) */
export_offset, /* offset to export table (>= 0) */
import_count, /* num. imports in export table (>= 0) */
import_offset; /* offset to import table (>= 0) */
/* number of GUIDs in heritage table (>= 1) and table's offset:
* only with versions < 68. */
int32_t heritage_count, heritage_offset;
#if 0
/* with versions >= 68: a GUID, a dword for generation count
* and export_count and name_count dwords for each generation: */
uint32_t guid[4];
int32_t generation_count;
struct _genhist {
int32_t export_count,
name_count;
} genhist[0/* generation_count */];
#endif
};
#pragma pack()
/* read Little Endian data in an endian-neutral way */
#define READ_INT32(b) ((b)[0] | ((b)[1] << 8) | ((b)[2] << 16) | ((b)[3] << 24))
#define UMUSIC_IT 0
#define UMUSIC_S3M 1
#define UMUSIC_XM 2
#define UMUSIC_MOD 3
#define UMUSIC_WAV 4
#define UMUSIC_MP2 5
static const char *mustype[] = {
"IT", "S3M", "XM", "MOD",
"WAV", "MP2", NULL
};
/* decode an FCompactIndex. original documentation by Tim Sweeney
* was at http://unreal.epicgames.com/Packages.htm
*/
static int32_t get_fci (const char *in, int *pos)
{
int32_t a;
int size;
size = 1;
a = in[0] & 0x3f;
if (in[0] & 0x40) {
size++;
a |= (in[1] & 0x7f) << 6;
if (in[1] & 0x80) {
size++;
a |= (in[2] & 0x7f) << 13;
if (in[2] & 0x80) {
size++;
a |= (in[3] & 0x7f) << 20;
if (in[3] & 0x80) {
size++;
a |= (in[4] & 0x3f) << 27;
}
}
}
}
if (in[0] & 0x80)
a = -a;
*pos += size;
return a;
}
static int get_objtype (fshandle_t *f, int32_t ofs, int type)
{
char sig[16];
_retry:
FS_fseek(f, ofs, SEEK_SET);
FS_fread(sig, 16, 1, f);
if (type == UMUSIC_IT) {
if (memcmp(sig, "IMPM", 4) == 0)
return UMUSIC_IT;
return -1;
}
if (type == UMUSIC_XM) {
if (memcmp(sig, "Extended Module:", 16) == 0)
return UMUSIC_XM;
return -1;
}
if (type == UMUSIC_MP2) {
unsigned char *p = (unsigned char *)sig;
uint16_t u = ((p[0] << 8) | p[1]) & 0xFFFE;
if (u == 0xFFFC || u == 0xFFF4)
return UMUSIC_MP2;
return -1;
}
if (type == UMUSIC_WAV) {
if (memcmp(sig, "RIFF", 4) == 0 && memcmp(&sig[8], "WAVE", 4) == 0)
return UMUSIC_WAV;
return -1;
}
FS_fseek(f, ofs + 44, SEEK_SET);
FS_fread(sig, 4, 1, f);
if (type == UMUSIC_S3M) {
if (memcmp(sig, "SCRM", 4) == 0)
return UMUSIC_S3M;
/*return -1;*/
/* SpaceMarines.umx and Starseek.umx from Return to NaPali
* report as "s3m" whereas the actual music format is "it" */
type = UMUSIC_IT;
goto _retry;
}
FS_fseek(f, ofs + 1080, SEEK_SET);
FS_fread(sig, 4, 1, f);
if (type == UMUSIC_MOD) {
if (memcmp(sig, "M.K.", 4) == 0 || memcmp(sig, "M!K!", 4) == 0)
return UMUSIC_MOD;
return -1;
}
return -1;
}
static int read_export (fshandle_t *f, const struct upkg_hdr *hdr,
int32_t *ofs, int32_t *objsize)
{
char buf[40];
int idx = 0, t;
FS_fseek(f, *ofs, SEEK_SET);
if (FS_fread(buf, 4, 10, f) < 10)
return -1;
get_fci(&buf[idx], &idx); /* skip junk */
t = get_fci(&buf[idx], &idx); /* type_name */
if (hdr->file_version > 61) idx += 4; /* skip export size */
*objsize = get_fci(&buf[idx], &idx);
*ofs += idx; /* offset for real data */
return t; /* return type_name index */
}
static int read_typname(fshandle_t *f, const struct upkg_hdr *hdr,
int idx, char *out)
{
int i, s;
long l;
char buf[64];
if (idx >= hdr->name_count) return -1;
for (i = 0, l = 0; i <= idx; i++) {
FS_fseek(f, hdr->name_offset + l, SEEK_SET);
FS_fread(buf, 1, 64, f);
if (hdr->file_version >= 64) {
s = *(signed char *)buf; /* numchars *including* terminator */
if (s <= 0 || s >= 64) return -1;
l += s + 5; /* 1 for buf[0], 4 for int32_t name_flags */
} else {
buf[63] = 0;
l += (long)strlen(buf);
l += 5; /* 1 for terminator, 4 for int32_t name_flags */
}
}
strcpy(out, (hdr->file_version >= 64)? &buf[1] : buf);
return 0;
}
static int probe_umx (fshandle_t *f, const struct upkg_hdr *hdr,
int32_t *ofs, int32_t *objsize)
{
int i, idx, t;
int32_t s, pos;
long fsiz;
char buf[64];
idx = 0;
fsiz = f->length;
/* Find the offset and size of the first IT, S3M or XM
* by parsing the exports table. The umx files should
* have only one export. Kran32.umx from Unreal has two,
* but both pointing to the same music. */
if (hdr->export_offset >= fsiz) return -1;
memset(buf, 0, 64);
FS_fseek(f, hdr->export_offset, SEEK_SET);
FS_fread(buf, 1, 64, f);
get_fci(&buf[idx], &idx); /* skip class_index */
idx += 4; /* skip int32 package_index */
get_fci(&buf[idx], &idx); /* skip super_index */
get_fci(&buf[idx], &idx); /* skip object_name */
idx += 4; /* skip int32 object_flags */
s = get_fci(&buf[idx], &idx); /* get serial_size */
if (s <= 0) return -1;
pos = get_fci(&buf[idx],&idx); /* get serial_offset */
if (pos < 0 || pos > fsiz - 40) return -1;
if ((t = read_export(f, hdr, &pos, &s)) < 0) return -1;
if (s <= 0 || s > fsiz - pos) return -1;
if (read_typname(f, hdr, t, buf) < 0) return -1;
for (i = 0; mustype[i] != NULL; i++) {
if (!strcasecmp(buf, mustype[i])) {
t = i;
break;
}
}
if (mustype[i] == NULL) return -1;
if ((t = get_objtype(f, pos, t)) < 0) return -1;
*ofs = pos;
*objsize = s;
return t;
}
static int32_t probe_header (void *header)
{
struct upkg_hdr *hdr;
unsigned char *p;
uint32_t *swp;
int i;
/* byte swap the header - all members are 32 bit LE values */
p = (unsigned char *) header;
swp = (uint32_t *) header;
for (i = 0; i < (int)sizeof(struct upkg_hdr)/4; i++, p += 4) {
swp[i] = READ_INT32(p);
}
hdr = (struct upkg_hdr *) header;
if (hdr->tag != UPKG_HDR_TAG) {
Con_DPrintf("Unknown header tag 0x%x\n", hdr->tag);
return -1;
}
if (hdr->name_count < 0 ||
hdr->name_offset < 0 ||
hdr->export_count < 0 ||
hdr->export_offset < 0 ||
hdr->import_count < 0 ||
hdr->import_offset < 0 ) {
Con_DPrintf("Negative values in header\n");
return -1;
}
switch (hdr->file_version) {
case 61:/* Unreal */
case 62:/* Unreal Tournament */
case 63:/* Return to NaPali */
case 64:/* Unreal Tournament */
case 66:/* Unreal Tournament */
case 68:/* Unreal Tournament */
case 69:/* Tactical Ops */
case 75:/* Harry Potter and the Philosopher's Stone */
case 76: /* mpeg layer II data */
case 83:/* Mobile Forces */
return 0;
}
Con_DPrintf("Unknown upkg version %d\n", hdr->file_version);
return -1;
}
static int process_upkg (fshandle_t *f, int32_t *ofs, int32_t *objsize)
{
char header[64];
if (FS_fread(header, 1, 64, f) < 64)
return -1;
if (probe_header(header) < 0)
return -1;
return probe_umx(f, (struct upkg_hdr *)header, ofs, objsize);
}
static qboolean S_UMX_CodecInitialize (void)
{
return true;
}
static void S_UMX_CodecShutdown (void)
{
}
static qboolean S_UMX_CodecOpenStream (snd_stream_t *stream)
{
int32_t ofs, size;
int type;
type = process_upkg(&stream->fh, &ofs, &size);
if (type < 0) {
Con_DPrintf("%s: unrecognized umx\n", stream->name);
return false;
}
Con_DPrintf("%s: %s data @ 0x%x, %d bytes\n", stream->name, mustype[type], ofs, size);
/* hack the fshandle_t start pos and length members so
* that only the relevant data is accessed from now on */
stream->fh.start = ofs;
stream->fh.length = size;
FS_fseek(&stream->fh, 0, SEEK_SET);
switch (type) {
case UMUSIC_IT:
case UMUSIC_S3M:
case UMUSIC_XM:
case UMUSIC_MOD: return S_CodecForwardStream(stream, CODECTYPE_MOD);
case UMUSIC_WAV: return S_CodecForwardStream(stream, CODECTYPE_WAV);
case UMUSIC_MP2: return S_CodecForwardStream(stream, CODECTYPE_MP3);
}
return false;
}
static int S_UMX_CodecReadStream (snd_stream_t *stream, int bytes, void *buffer)
{
return -1;
}
static void S_UMX_CodecCloseStream (snd_stream_t *stream)
{
S_CodecUtilClose(&stream);
}
static int S_UMX_CodecRewindStream (snd_stream_t *stream)
{
return -1;
}
snd_codec_t umx_codec =
{
CODECTYPE_UMX,
true, /* always available. */
"umx",
S_UMX_CodecInitialize,
S_UMX_CodecShutdown,
S_UMX_CodecOpenStream,
S_UMX_CodecReadStream,
S_UMX_CodecRewindStream,
S_UMX_CodecCloseStream,
NULL
};
#endif /* USE_CODEC_UMX */

View file

@ -0,0 +1,12 @@
/* Unreal UMX format support */
#if !defined(_SND_UMX_H_)
#define _SND_UMX_H_
#if defined(USE_CODEC_UMX)
extern snd_codec_t umx_codec;
#endif /* USE_CODEC_UMX */
#endif /* ! _SND_UMX_H_ */

View file

@ -75,38 +75,33 @@ static void S_VORBIS_CodecShutdown (void)
{
}
static snd_stream_t *S_VORBIS_CodecOpenStream (const char *filename)
static qboolean S_VORBIS_CodecOpenStream (snd_stream_t *stream)
{
snd_stream_t *stream;
OggVorbis_File *ovFile;
vorbis_info *ovf_info;
long numstreams;
int res;
stream = S_CodecUtilOpen(filename, &vorbis_codec);
if (!stream)
return NULL;
ovFile = (OggVorbis_File *) Z_Malloc(sizeof(OggVorbis_File));
stream->priv = ovFile;
res = OV_OPEN_CALLBACKS(&stream->fh, ovFile, NULL, 0, ovc_qfs);
if (res != 0)
{
Con_Printf("%s is not a valid Ogg Vorbis file (error %i).\n",
filename, res);
stream->name, res);
goto _fail;
}
if (!ov_seekable(ovFile))
{
Con_Printf("Stream %s not seekable.\n", filename);
Con_Printf("Stream %s not seekable.\n", stream->name);
goto _fail;
}
ovf_info = ov_info(ovFile, 0);
if (!ovf_info)
{
Con_Printf("Unable to get stream info for %s.\n", filename);
Con_Printf("Unable to get stream info for %s.\n", stream->name);
goto _fail;
}
@ -115,14 +110,14 @@ static snd_stream_t *S_VORBIS_CodecOpenStream (const char *filename)
if (numstreams != 1)
{
Con_Printf("More than one (%ld) stream in %s.\n",
numstreams, filename);
numstreams, stream->name);
goto _fail;
}
if (ovf_info->channels != 1 && ovf_info->channels != 2)
{
Con_Printf("Unsupported number of channels %d in %s\n",
ovf_info->channels, filename);
ovf_info->channels, stream->name);
goto _fail;
}
@ -131,13 +126,12 @@ static snd_stream_t *S_VORBIS_CodecOpenStream (const char *filename)
stream->info.bits = VORBIS_SAMPLEBITS;
stream->info.width = VORBIS_SAMPLEWIDTH;
return stream;
return true;
_fail:
if (res == 0)
ov_clear(ovFile);
Z_Free(ovFile);
S_CodecUtilClose(&stream);
return NULL;
return false;
}
static int S_VORBIS_CodecReadStream (snd_stream_t *stream, int bytes, void *buffer)

View file

@ -192,35 +192,25 @@ static qboolean WAV_ReadRIFFHeader(const char *name, FILE *file, snd_info_t *inf
S_WAV_CodecOpenStream
=================
*/
snd_stream_t *S_WAV_CodecOpenStream(const char *filename)
static qboolean S_WAV_CodecOpenStream(snd_stream_t *stream)
{
snd_stream_t *stream;
long start;
stream = S_CodecUtilOpen(filename, &wav_codec);
if (!stream)
return NULL;
start = stream->fh.start;
long start = stream->fh.start;
/* Read the RIFF header */
/* The file reads are sequential, therefore no need
* for the FS_*() functions: We will manipulate the
* file by ourselves from now on. */
if (!WAV_ReadRIFFHeader(filename, stream->fh.file, &stream->info))
goto _fail;
if (!WAV_ReadRIFFHeader(stream->name, stream->fh.file, &stream->info))
return false;
stream->fh.start = ftell(stream->fh.file); /* reset to data position */
if (stream->fh.start - start + stream->info.size > stream->fh.length)
{
Con_Printf("%s data size mismatch\n", filename);
goto _fail;
Con_Printf("%s data size mismatch\n", stream->name);
return false;
}
return stream;
_fail:
S_CodecUtilClose(&stream);
return NULL;
return true;
}
/*