From 81a318c09b0856f7aff5e62861611c4b6f7c67a4 Mon Sep 17 00:00:00 2001 From: sezero Date: Mon, 14 Feb 2011 20:02:52 +0000 Subject: [PATCH] * snd_mpg123.c: added new codec for mp3 playback using libmpg123 as an alternative to the existing one using libmad. requires at least mpg123-1.12.0, i.e. api version 25. git-svn-id: http://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@414 af15c1b1-3010-417e-b628-4374ebc0bcbd --- Quake/Makefile | 18 +++- Quake/Makefile.darwin | 18 +++- Quake/Makefile.w32 | 18 +++- Quake/Makefile.w64 | 18 +++- Quake/snd_mp3.h | 2 +- Quake/snd_mpg123.c | 225 ++++++++++++++++++++++++++++++++++++++++++ README.html | 2 +- README.sgml | 2 +- README.txt | 4 +- 9 files changed, 294 insertions(+), 13 deletions(-) create mode 100644 Quake/snd_mpg123.c diff --git a/Quake/Makefile b/Quake/Makefile index 45322db1..d89f0cdd 100644 --- a/Quake/Makefile +++ b/Quake/Makefile @@ -19,6 +19,9 @@ USE_CODEC_WAVE=1 USE_CODEC_MP3=1 USE_CODEC_VORBIS=1 +# which library to use for mp3 decoding: mad or mpg123 +MP3LIB=mad + # ============================================================================ # Helper functions # ============================================================================ @@ -121,6 +124,17 @@ ifeq ($(USE_QS_CONBACK),1) CFLAGS+= -DUSE_QS_CONBACK endif +ifeq ($(MP3LIB),mad) +mp3_obj=snd_mp3.o +else +ifeq ($(MP3LIB),mpg123) +mp3_obj=snd_mpg123.o +else +USE_CODEC_MP3=no +mp3_obj=snd_mp3.o +endif +endif + CODECLIBS := ifeq ($(USE_CODEC_WAVE),1) CFLAGS+= -DUSE_CODEC_WAVE @@ -131,7 +145,7 @@ CODECLIBS+= vorbis vorbisfile ogg endif ifeq ($(USE_CODEC_MP3),1) CFLAGS+= -DUSE_CODEC_MP3 -CODECLIBS+= mad +CODECLIBS+= $(MP3LIB) endif COMMON_LIBS:= m GL @@ -161,7 +175,7 @@ MUSIC_OBJS:= bgmusic.o \ snd_codec.o \ snd_wave.o \ snd_vorbis.o \ - snd_mp3.o + $(mp3_obj) COMOBJ_SND := snd_dma.o snd_mix.o snd_mem.o $(MUSIC_OBJS) SYSOBJ_SND := snd_sdl.o SYSOBJ_CDA := cd_sdl.o diff --git a/Quake/Makefile.darwin b/Quake/Makefile.darwin index cfcc44b7..cea016b5 100644 --- a/Quake/Makefile.darwin +++ b/Quake/Makefile.darwin @@ -18,6 +18,9 @@ USE_CODEC_WAVE=1 USE_CODEC_MP3=1 USE_CODEC_VORBIS=1 +# which library to use for mp3 decoding: mad or mpg123 +MP3LIB=mad + # ============================================================================ # Helper functions # ============================================================================ @@ -127,6 +130,17 @@ ifeq ($(USE_QS_CONBACK),1) CFLAGS+= -DUSE_QS_CONBACK endif +ifeq ($(MP3LIB),mad) +mp3_obj=snd_mp3.o +else +ifeq ($(MP3LIB),mpg123) +mp3_obj=snd_mpg123.o +else +USE_CODEC_MP3=no +mp3_obj=snd_mp3.o +endif +endif + # FIXME: The codec libs stuff are copied over from the unix makefile # They might need adaptations for Darwin CODECLIBS := @@ -139,7 +153,7 @@ CODECLIBS+= -lvorbis -lvorbisfile -logg endif ifeq ($(USE_CODEC_MP3),1) CFLAGS+= -DUSE_CODEC_MP3 -CODECLIBS+= -lmad +CODECLIBS+= -l$(MP3LIB) endif COMMON_LIBS = -Wl,-framework,OpenGL @@ -170,7 +184,7 @@ MUSIC_OBJS:= bgmusic.o \ snd_codec.o \ snd_wave.o \ snd_vorbis.o \ - snd_mp3.o + $(mp3_obj) COMOBJ_SND := snd_dma.o snd_mix.o snd_mem.o $(MUSIC_OBJS) SYSOBJ_SND := snd_sdl.o SYSOBJ_CDA := cd_sdl.o diff --git a/Quake/Makefile.w32 b/Quake/Makefile.w32 index 6880a5db..8cb20a3d 100644 --- a/Quake/Makefile.w32 +++ b/Quake/Makefile.w32 @@ -14,6 +14,9 @@ USE_CODEC_WAVE=1 USE_CODEC_MP3=1 USE_CODEC_VORBIS=1 +# which library to use for mp3 decoding: mad or mpg123 +MP3LIB=mad + # ============================================================================ # Helper functions # ============================================================================ @@ -93,6 +96,17 @@ ifeq ($(USE_QS_CONBACK),1) CFLAGS+= -DUSE_QS_CONBACK endif +ifeq ($(MP3LIB),mad) +mp3_obj=snd_mp3.o +else +ifeq ($(MP3LIB),mpg123) +mp3_obj=snd_mpg123.o +else +USE_CODEC_MP3=no +mp3_obj=snd_mp3.o +endif +endif + CODECLIBS := ifeq ($(USE_CODEC_WAVE),1) CFLAGS+= -DUSE_CODEC_WAVE @@ -109,7 +123,7 @@ ifeq ($(USE_CODEC_MP3),1) CFLAGS+= -DUSE_CODEC_MP3 CODEC_INC = -I../Windows/codecs/include CODEC_LINK= -L../Windows/codecs/x86 -CODECLIBS+= -lmad +CODECLIBS+= -l$(MP3LIB) endif CFLAGS+= $(CODEC_INC) @@ -142,7 +156,7 @@ MUSIC_OBJS:= bgmusic.o \ snd_codec.o \ snd_wave.o \ snd_vorbis.o \ - snd_mp3.o + $(mp3_obj) COMOBJ_SND := snd_dma.o snd_mix.o snd_mem.o $(MUSIC_OBJS) SYSOBJ_SND := snd_sdl.o SYSOBJ_CDA := cd_sdl.o diff --git a/Quake/Makefile.w64 b/Quake/Makefile.w64 index 6947c063..ea9b3ffc 100644 --- a/Quake/Makefile.w64 +++ b/Quake/Makefile.w64 @@ -14,6 +14,9 @@ USE_CODEC_WAVE=1 USE_CODEC_MP3=1 USE_CODEC_VORBIS=1 +# which library to use for mp3 decoding: mad or mpg123 +MP3LIB=mad + # ============================================================================ # Helper functions # ============================================================================ @@ -93,6 +96,17 @@ ifeq ($(USE_QS_CONBACK),1) CFLAGS+= -DUSE_QS_CONBACK endif +ifeq ($(MP3LIB),mad) +mp3_obj=snd_mp3.o +else +ifeq ($(MP3LIB),mpg123) +mp3_obj=snd_mpg123.o +else +USE_CODEC_MP3=no +mp3_obj=snd_mp3.o +endif +endif + CODECLIBS := ifeq ($(USE_CODEC_WAVE),1) CFLAGS+= -DUSE_CODEC_WAVE @@ -109,7 +123,7 @@ ifeq ($(USE_CODEC_MP3),1) CFLAGS+= -DUSE_CODEC_MP3 CODEC_INC = -I../Windows/codecs/include CODEC_LINK= -L../Windows/codecs/x64 -CODECLIBS+= -lmad +CODECLIBS+= -l$(MP3LIB) endif CFLAGS+= $(CODEC_INC) @@ -142,7 +156,7 @@ MUSIC_OBJS:= bgmusic.o \ snd_codec.o \ snd_wave.o \ snd_vorbis.o \ - snd_mp3.o + $(mp3_obj) COMOBJ_SND := snd_dma.o snd_mix.o snd_mem.o $(MUSIC_OBJS) SYSOBJ_SND := snd_sdl.o SYSOBJ_CDA := cd_sdl.o diff --git a/Quake/snd_mp3.h b/Quake/snd_mp3.h index 69a1c973..d54ae4dc 100644 --- a/Quake/snd_mp3.h +++ b/Quake/snd_mp3.h @@ -1,4 +1,4 @@ -/* MP3 decoding support using libmad. */ +/* MP3 decoding support using libmad or libmpg123. */ #if !defined(_SND_MP3_H_) #define _SND_MP3_H_ diff --git a/Quake/snd_mpg123.c b/Quake/snd_mpg123.c new file mode 100644 index 00000000..6e69a514 --- /dev/null +++ b/Quake/snd_mpg123.c @@ -0,0 +1,225 @@ +/* + * MP3 decoding support using libmpg123, loosely based on an SDL_mixer + * plugin found at http://bubu.lv/ + * See: http://bubu.lv/changeset/4/public/libs/SDL/generated/SDL_mixer + * + * Copyright (C) 2011 O.Sezer + * + * 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_MP3) +#include "snd_codec.h" +#include "snd_codeci.h" +#include "snd_mp3.h" +#include +#include + +#if !defined(MPG123_API_VERSION) || (MPG123_API_VERSION < 25) +#error minimum required libmpg123 version is 1.12.0 (api version 25) +#endif /* MPG123_API_VERSION */ + +/* Private data */ +typedef struct _mp3_priv_t +{ + int handle_newed, handle_opened; + mpg123_handle* handle; +} mp3_priv_t; + +/* CALLBACK FUNCTIONS: */ +/* CAREFUL: libmpg123 expects POSIX read() and lseek() behavior, + * however our FS_fread() and FS_fseek() return fread() and fseek() + * compatible values. */ + +static ssize_t mp3_read (void *f, void *buf, size_t size) +{ + ssize_t ret = (ssize_t) FS_fread(buf, 1, size, (fshandle_t *)f); + if (ret == 0 && errno != 0) + ret = -1; + return ret; +} + +static off_t mp3_seek (void *f, off_t offset, int whence) +{ + if (f == NULL) return (-1); + if (FS_fseek((fshandle_t *)f, (long) offset, whence) < 0) + return (off_t)-1; + return (off_t) FS_ftell((fshandle_t *)f); +} + +static qboolean S_MP3_CodecInitialize (void) +{ + if (! mp3_codec.initialized) + { + if (mpg123_init() != MPG123_OK) + return false; + mp3_codec.initialized = true; + return true; + } + + return true; +} + +static void S_MP3_CodecShutdown (void) +{ + if (mp3_codec.initialized) + { + mp3_codec.initialized = false; + mpg123_exit(); + } +} + +static snd_stream_t *S_MP3_CodecOpenStream (const char *filename) +{ + 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); + if (priv->handle == NULL) + { + Con_Printf("Unable to allocate mpg123 handle\n"); + goto _fail; + } + priv->handle_newed = 1; + + if (mpg123_replace_reader_handle(priv->handle, mp3_read, mp3_seek, NULL) != MPG123_OK || + mpg123_open_handle(priv->handle, &stream->fh) != MPG123_OK) + { + Con_Printf("Unable to open mpg123 handle\n"); + goto _fail; + } + priv->handle_opened = 1; + + if (mpg123_getformat(priv->handle, &rate, &channels, &encoding) != MPG123_OK) + { + Con_Printf("Unable to retrieve mpg123 format for %s\n", filename); + goto _fail; + } + + switch (channels) + { + case MPG123_MONO: + stream->info.channels = 1; + break; + case MPG123_STEREO: + stream->info.channels = 2; + break; + default: + Con_Printf("Unsupported channel count in %s\n", filename); + goto _fail; + } + + stream->info.rate = rate; + + switch (encoding) + { + case MPG123_ENC_UNSIGNED_8: + stream->info.width = 1; + break; + case MPG123_ENC_SIGNED_8: + /* unsupported: force mpg123 to convert */ + stream->info.width = 1; + encoding = MPG123_ENC_UNSIGNED_8; + break; + case MPG123_ENC_SIGNED_16: + stream->info.width = 2; + break; + case MPG123_ENC_UNSIGNED_16: + default: + /* unsupported: force mpg123 to convert */ + stream->info.width = 2; + encoding = MPG123_ENC_SIGNED_16; + break; + } + if (mpg123_format_support(priv->handle, rate, encoding) == 0) + { + Con_Printf("Unsupported format for %s\n", filename); + goto _fail; + } + mpg123_format_none(priv->handle); + mpg123_format(priv->handle, rate, channels, encoding); + + return stream; +_fail: + if (priv) + { + if (priv->handle_opened) + mpg123_close(priv->handle); + if (priv->handle_newed) + mpg123_delete(priv->handle); + Z_Free(stream->priv); + } + S_CodecUtilClose(&stream); + return NULL; +} + +static int S_MP3_CodecReadStream (snd_stream_t *stream, int bytes, void *buffer) +{ + mp3_priv_t *priv = (mp3_priv_t *) stream->priv; + size_t bytes_read = 0; + int res = mpg123_read (priv->handle, (unsigned char *)buffer, (size_t)bytes, &bytes_read); + switch (res) + { + case MPG123_DONE: + Con_DPrintf("mp3 EOF\n"); + case MPG123_OK: + return (int)bytes_read; + } + return -1; /* error */ +} + +static void S_MP3_CodecCloseStream (snd_stream_t *stream) +{ + mp3_priv_t *priv = (mp3_priv_t *) stream->priv; + mpg123_close(priv->handle); + mpg123_delete(priv->handle); + Z_Free(stream->priv); + S_CodecUtilClose(&stream); +} + +static int S_MP3_CodecRewindStream (snd_stream_t *stream) +{ + mp3_priv_t *priv = (mp3_priv_t *) stream->priv; + return (int) mpg123_seek(priv->handle, 0, SEEK_SET); +} + +snd_codec_t mp3_codec = +{ + CODECTYPE_MP3, + false, + ".mp3", + S_MP3_CodecInitialize, + S_MP3_CodecShutdown, + S_MP3_CodecOpenStream, + S_MP3_CodecReadStream, + S_MP3_CodecRewindStream, + S_MP3_CodecCloseStream, + NULL +}; + +#endif /* USE_CODEC_MP3 */ + diff --git a/README.html b/README.html index 4d80293d..60bd06db 100644 --- a/README.html +++ b/README.html @@ -113,7 +113,7 @@ Compile time options include
  • make SDL_CONFIG=/PATH/TO/SDL-CONFIG for unusual SDL installs
  • -

    Streaming music playback requires "libmad" for MP3, and "libogg", "libvorbis" for OGG files.

    +

    Streaming music playback requires "libmad" or "libmpg123" for MP3, and "libogg" and "libvorbis" for OGG files.

    HOME directory support can be enabled via the Misc/homedir_0.patch

    The project can also be built with Codeblocks (project files included).

    . diff --git a/README.sgml b/README.sgml index 4adb0fcb..cf87465f 100644 --- a/README.sgml +++ b/README.sgml @@ -66,7 +66,7 @@ Compile time options include make SDLNET=1 to enable SDL_net (Otherwise the socket api will be used directly) make SDL_CONFIG=/PATH/TO/SDL-CONFIG for unusual SDL installs -

    Streaming music playback requires "libmad" for MP3, and "libogg", "libvorbis" for OGG files. +

    Streaming music playback requires "libmad" or "libmpg123" for MP3, and "libogg" and "libvorbis" for OGG files.

    HOME directory support can be enabled via the Misc/homedir_0.patch

    The project can also be built with Codeblocks (project files included).

    . diff --git a/README.txt b/README.txt index 1cf057c3..fa570070 100644 --- a/README.txt +++ b/README.txt @@ -109,8 +109,8 @@ o make SDL_CONFIG=/PATH/TO/SDL-CONFIG for unusual SDL installs - Streaming music playback requires "libmad" for MP3, and "libogg", - "libvorbis" for OGG files. + Streaming music playback requires "libmad" or "libmpg123" for MP3, and + "libogg" and "libvorbis" for OGG files. HOME directory support can be enabled via the Misc/homedir_0.patch