From 9383301a6b3d024b14991165e5eafc82cc50432c 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: svn+ssh://svn.code.sf.net/p/quakespasm/code/trunk@414 af15c1b1-3010-417e-b628-4374ebc0bcbd
---
quakespasm/Quake/Makefile | 18 ++-
quakespasm/Quake/Makefile.darwin | 18 ++-
quakespasm/Quake/Makefile.w32 | 18 ++-
quakespasm/Quake/Makefile.w64 | 18 ++-
quakespasm/Quake/snd_mp3.h | 2 +-
quakespasm/Quake/snd_mpg123.c | 225 +++++++++++++++++++++++++++++++
quakespasm/README.html | 2 +-
quakespasm/README.sgml | 2 +-
quakespasm/README.txt | 4 +-
9 files changed, 294 insertions(+), 13 deletions(-)
create mode 100644 quakespasm/Quake/snd_mpg123.c
diff --git a/quakespasm/Quake/Makefile b/quakespasm/Quake/Makefile
index 45322db1..d89f0cdd 100644
--- a/quakespasm/Quake/Makefile
+++ b/quakespasm/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/quakespasm/Quake/Makefile.darwin b/quakespasm/Quake/Makefile.darwin
index cfcc44b7..cea016b5 100644
--- a/quakespasm/Quake/Makefile.darwin
+++ b/quakespasm/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/quakespasm/Quake/Makefile.w32 b/quakespasm/Quake/Makefile.w32
index 6880a5db..8cb20a3d 100644
--- a/quakespasm/Quake/Makefile.w32
+++ b/quakespasm/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/quakespasm/Quake/Makefile.w64 b/quakespasm/Quake/Makefile.w64
index 6947c063..ea9b3ffc 100644
--- a/quakespasm/Quake/Makefile.w64
+++ b/quakespasm/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/quakespasm/Quake/snd_mp3.h b/quakespasm/Quake/snd_mp3.h
index 69a1c973..d54ae4dc 100644
--- a/quakespasm/Quake/snd_mp3.h
+++ b/quakespasm/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/quakespasm/Quake/snd_mpg123.c b/quakespasm/Quake/snd_mpg123.c
new file mode 100644
index 00000000..6e69a514
--- /dev/null
+++ b/quakespasm/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/quakespasm/README.html b/quakespasm/README.html
index 4d80293d..60bd06db 100644
--- a/quakespasm/README.html
+++ b/quakespasm/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/quakespasm/README.sgml b/quakespasm/README.sgml
index 4adb0fcb..cf87465f 100644
--- a/quakespasm/README.sgml
+++ b/quakespasm/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/quakespasm/README.txt b/quakespasm/README.txt
index 1cf057c3..fa570070 100644
--- a/quakespasm/README.txt
+++ b/quakespasm/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