mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2024-11-10 07:21:58 +00:00
Opus decoding support (as an optional patch only.)
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@824 af15c1b1-3010-417e-b628-4374ebc0bcbd
This commit is contained in:
parent
8bfd0fe0e8
commit
024dab7f8a
1 changed files with 423 additions and 0 deletions
423
Misc/snd_opus.patch
Normal file
423
Misc/snd_opus.patch
Normal file
|
@ -0,0 +1,423 @@
|
|||
Opus file decoding support. it is not enabled by default: just edit
|
||||
the Makefile for USE_CODEC_OPUS.
|
||||
|
||||
2013.02.28 O.Sezer <sezero@users.sourceforge.net>
|
||||
|
||||
Index: bgmusic.c
|
||||
===================================================================
|
||||
--- bgmusic.c (revision 823)
|
||||
+++ bgmusic.c (working copy)
|
||||
@@ -54,6 +54,7 @@
|
||||
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 },
|
||||
Index: snd_codec.c
|
||||
===================================================================
|
||||
--- snd_codec.c (revision 823)
|
||||
+++ snd_codec.c (working copy)
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "snd_wave.h"
|
||||
#include "snd_mp3.h"
|
||||
#include "snd_vorbis.h"
|
||||
+#include "snd_opus.h"
|
||||
|
||||
|
||||
static snd_codec_t *codecs;
|
||||
@@ -67,6 +68,9 @@
|
||||
#ifdef USE_CODEC_VORBIS
|
||||
S_CodecRegister(&vorbis_codec);
|
||||
#endif
|
||||
+#ifdef USE_CODEC_OPUS
|
||||
+ S_CodecRegister(&opus_codec);
|
||||
+#endif
|
||||
codec = codecs;
|
||||
while (codec)
|
||||
{
|
||||
Index: snd_codec.h
|
||||
===================================================================
|
||||
--- snd_codec.h (revision 823)
|
||||
+++ snd_codec.h (working copy)
|
||||
@@ -88,6 +88,7 @@
|
||||
#define CODECTYPE_WAV (1U << 3)
|
||||
#define CODECTYPE_MP3 (1U << 4)
|
||||
#define CODECTYPE_VORBIS (1U << 5)
|
||||
+#define CODECTYPE_OPUS (1U << 6)
|
||||
|
||||
#define CODECTYPE_WAVE CODECTYPE_WAV
|
||||
#define CODECTYPE_MIDI CODECTYPE_MID
|
||||
Index: Makefile
|
||||
===================================================================
|
||||
--- Makefile (revision 823)
|
||||
+++ Makefile (working copy)
|
||||
@@ -12,6 +12,7 @@
|
||||
USE_CODEC_WAVE=1
|
||||
USE_CODEC_MP3=1
|
||||
USE_CODEC_VORBIS=1
|
||||
+USE_CODEC_OPUS=0
|
||||
|
||||
# which library to use for mp3 decoding: mad or mpg123
|
||||
MP3LIB=mad
|
||||
@@ -135,6 +136,14 @@
|
||||
ifeq ($(USE_CODEC_WAVE),1)
|
||||
CFLAGS+= -DUSE_CODEC_WAVE
|
||||
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)
|
||||
@@ -171,6 +180,7 @@
|
||||
snd_codec.o \
|
||||
snd_wave.o \
|
||||
snd_vorbis.o \
|
||||
+ snd_opus.o \
|
||||
$(mp3_obj)
|
||||
COMOBJ_SND := snd_dma.o snd_mix.o snd_mem.o $(MUSIC_OBJS)
|
||||
SYSOBJ_SND := snd_sdl.o
|
||||
Index: Makefile.darwin
|
||||
===================================================================
|
||||
--- Makefile.darwin (revision 823)
|
||||
+++ Makefile.darwin (working copy)
|
||||
@@ -13,6 +13,7 @@
|
||||
USE_CODEC_WAVE=1
|
||||
USE_CODEC_MP3=1
|
||||
USE_CODEC_VORBIS=1
|
||||
+USE_CODEC_OPUS=0
|
||||
|
||||
# which library to use for mp3 decoding: mad or mpg123
|
||||
MP3LIB=mad
|
||||
@@ -123,6 +124,12 @@
|
||||
ifeq ($(USE_CODEC_WAVE),1)
|
||||
CFLAGS+= -DUSE_CODEC_WAVE
|
||||
endif
|
||||
+ifeq ($(USE_CODEC_OPUS),1)
|
||||
+CFLAGS+= -DUSE_CODEC_OPUS
|
||||
+CODEC_INC = -I../MacOSX/codecs/include
|
||||
+CODEC_LINK= -L../MacOSX/codecs/lib
|
||||
+CODECLIBS+= -lopusfile -lopus -logg
|
||||
+endif
|
||||
ifeq ($(USE_CODEC_VORBIS),1)
|
||||
CFLAGS+= -DUSE_CODEC_VORBIS $(cpp_vorbisdec)
|
||||
CODEC_INC = -I../MacOSX/codecs/include
|
||||
@@ -168,6 +175,7 @@
|
||||
snd_codec.o \
|
||||
snd_wave.o \
|
||||
snd_vorbis.o \
|
||||
+ snd_opus.o \
|
||||
$(mp3_obj)
|
||||
COMOBJ_SND := snd_dma.o snd_mix.o snd_mem.o $(MUSIC_OBJS)
|
||||
SYSOBJ_SND := snd_sdl.o
|
||||
Index: Makefile.w32
|
||||
===================================================================
|
||||
--- Makefile.w32 (revision 823)
|
||||
+++ Makefile.w32 (working copy)
|
||||
@@ -13,6 +13,7 @@
|
||||
USE_CODEC_WAVE=1
|
||||
USE_CODEC_MP3=1
|
||||
USE_CODEC_VORBIS=1
|
||||
+USE_CODEC_OPUS=0
|
||||
|
||||
# which library to use for mp3 decoding: mad or mpg123
|
||||
MP3LIB=mad
|
||||
@@ -131,6 +132,12 @@
|
||||
CODEC_INC = -I../Windows/codecs/include
|
||||
CODEC_LINK= -L../Windows/codecs/x86
|
||||
endif
|
||||
+ifeq ($(USE_CODEC_OPUS),1)
|
||||
+CFLAGS+= -DUSE_CODEC_OPUS
|
||||
+CODEC_INC = -I../Windows/codecs/include
|
||||
+CODEC_LINK= -L../Windows/codecs/x86
|
||||
+CODECLIBS+= -lopusfile -lopus -logg
|
||||
+endif
|
||||
ifeq ($(USE_CODEC_VORBIS),1)
|
||||
CFLAGS+= -DUSE_CODEC_VORBIS $(cpp_vorbisdec)
|
||||
CODEC_INC = -I../Windows/codecs/include
|
||||
@@ -174,6 +181,7 @@
|
||||
snd_codec.o \
|
||||
snd_wave.o \
|
||||
snd_vorbis.o \
|
||||
+ snd_opus.o \
|
||||
$(mp3_obj)
|
||||
COMOBJ_SND := snd_dma.o snd_mix.o snd_mem.o $(MUSIC_OBJS)
|
||||
SYSOBJ_SND := snd_sdl.o
|
||||
Index: Makefile.w64
|
||||
===================================================================
|
||||
--- Makefile.w64 (revision 823)
|
||||
+++ Makefile.w64 (working copy)
|
||||
@@ -13,6 +13,7 @@
|
||||
USE_CODEC_WAVE=1
|
||||
USE_CODEC_MP3=1
|
||||
USE_CODEC_VORBIS=1
|
||||
+USE_CODEC_OPUS=0
|
||||
|
||||
# which library to use for mp3 decoding: mad or mpg123
|
||||
MP3LIB=mad
|
||||
@@ -131,6 +132,12 @@
|
||||
CODEC_INC = -I../Windows/codecs/include
|
||||
CODEC_LINK= -L../Windows/codecs/x64
|
||||
endif
|
||||
+ifeq ($(USE_CODEC_OPUS),1)
|
||||
+CFLAGS+= -DUSE_CODEC_OPUS
|
||||
+CODEC_INC = -I../Windows/codecs/include
|
||||
+CODEC_LINK= -L../Windows/codecs/x64
|
||||
+CODECLIBS+= -lopusfile -lopus -logg
|
||||
+endif
|
||||
ifeq ($(USE_CODEC_VORBIS),1)
|
||||
CFLAGS+= -DUSE_CODEC_VORBIS $(cpp_vorbisdec)
|
||||
CODEC_INC = -I../Windows/codecs/include
|
||||
@@ -174,6 +181,7 @@
|
||||
snd_codec.o \
|
||||
snd_wave.o \
|
||||
snd_vorbis.o \
|
||||
+ snd_opus.o \
|
||||
$(mp3_obj)
|
||||
COMOBJ_SND := snd_dma.o snd_mix.o snd_mem.o $(MUSIC_OBJS)
|
||||
SYSOBJ_SND := snd_sdl.o
|
||||
Index: snd_opus.c
|
||||
===================================================================
|
||||
--- snd_opus.c (revision 0)
|
||||
+++ snd_opus.c (revision 0)
|
||||
@@ -0,0 +1,215 @@
|
||||
+/*
|
||||
+ * Ogg/Opus streaming music support, loosely based on several open source
|
||||
+ * Quake engine based projects with many modifications.
|
||||
+ *
|
||||
+ * Copyright (C) 2012-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_OPUS)
|
||||
+#include "snd_codec.h"
|
||||
+#include "snd_codeci.h"
|
||||
+#include "snd_opus.h"
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <opusfile.h>
|
||||
+
|
||||
+
|
||||
+/* CALLBACK FUNCTIONS: */
|
||||
+
|
||||
+static int opc_fclose (void *f)
|
||||
+{
|
||||
+ return 0; /* we fclose() elsewhere. */
|
||||
+}
|
||||
+
|
||||
+static int opc_fread (void *f, unsigned char *buf, int size)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ if (size < 0)
|
||||
+ {
|
||||
+ errno = EINVAL;
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ ret = (int) FS_fread(buf, 1, (size_t)size, (fshandle_t *)f);
|
||||
+ if (ret == 0 && errno != 0)
|
||||
+ ret = -1;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int opc_fseek (void *f, opus_int64 off, int whence)
|
||||
+{
|
||||
+ if (f == NULL) return (-1);
|
||||
+ return FS_fseek((fshandle_t *)f, (long) off, whence);
|
||||
+}
|
||||
+
|
||||
+static opus_int64 opc_ftell (void *f)
|
||||
+{
|
||||
+ return (opus_int64) FS_ftell((fshandle_t *)f);
|
||||
+}
|
||||
+
|
||||
+static const OpusFileCallbacks opc_qfs =
|
||||
+{
|
||||
+ (int (*)(void *, unsigned char *, int)) opc_fread,
|
||||
+ (int (*)(void *, opus_int64, int)) opc_fseek,
|
||||
+ (opus_int64 (*)(void *)) opc_ftell,
|
||||
+ (int (*)(void *)) opc_fclose
|
||||
+};
|
||||
+
|
||||
+static qboolean S_OPUS_CodecInitialize (void)
|
||||
+{
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static void S_OPUS_CodecShutdown (void)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static snd_stream_t *S_OPUS_CodecOpenStream (const char *filename)
|
||||
+{
|
||||
+ 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);
|
||||
+ goto _fail;
|
||||
+ }
|
||||
+
|
||||
+ stream->priv = opFile;
|
||||
+
|
||||
+ if (!op_seekable(opFile))
|
||||
+ {
|
||||
+ Con_Printf("Opus stream %s not seekable.\n", filename);
|
||||
+ goto _fail;
|
||||
+ }
|
||||
+
|
||||
+ op_info = op_head(opFile, -1);
|
||||
+ if (!op_info)
|
||||
+ {
|
||||
+ Con_Printf("Unable to get stream information for %s.\n", filename);
|
||||
+ goto _fail;
|
||||
+ }
|
||||
+
|
||||
+ /* FIXME: handle section changes */
|
||||
+ numstreams = op_info->stream_count;
|
||||
+ if (numstreams != 1)
|
||||
+ {
|
||||
+ Con_Printf("More than one (%ld) stream in %s\n",
|
||||
+ (long)op_info->stream_count, filename);
|
||||
+ 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);
|
||||
+ goto _fail;
|
||||
+ }
|
||||
+
|
||||
+ /* All Opus audio is coded at 48 kHz, and should also be decoded
|
||||
+ * at 48 kHz for playback: info->input_sample_rate only tells us
|
||||
+ * the sampling rate of the original input before opus encoding.
|
||||
+ * S_RawSamples() shall already downsample this, as necessary. */
|
||||
+ stream->info.rate = 48000;
|
||||
+ stream->info.channels = op_info->channel_count;
|
||||
+ /* op_read() yields 16-bit output using native endian ordering: */
|
||||
+ stream->info.width = 2;
|
||||
+
|
||||
+ return stream;
|
||||
+_fail:
|
||||
+ if (opFile)
|
||||
+ op_free(opFile);
|
||||
+ S_CodecUtilClose(&stream);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static int S_OPUS_CodecReadStream (snd_stream_t *stream, int bytes, void *buffer)
|
||||
+{
|
||||
+ int section; /* FIXME: handle section changes */
|
||||
+ int cnt, res, rem;
|
||||
+ opus_int16 * ptr;
|
||||
+
|
||||
+ rem = bytes / stream->info.width;
|
||||
+ if (rem / stream->info.channels <= 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ cnt = 0;
|
||||
+ ptr = (opus_int16 *) buffer;
|
||||
+ while (1)
|
||||
+ {
|
||||
+ /* op_read() yields 16-bit output using native endian ordering. returns
|
||||
+ * the number of samples read per channel on success, or a negative value
|
||||
+ * on failure. */
|
||||
+ res = op_read((OggOpusFile *)stream->priv, ptr, rem, §ion);
|
||||
+ if (res <= 0)
|
||||
+ break;
|
||||
+ cnt += res;
|
||||
+ res *= stream->info.channels;
|
||||
+ rem -= res;
|
||||
+ if (rem <= 0)
|
||||
+ break;
|
||||
+ ptr += res;
|
||||
+ }
|
||||
+
|
||||
+ if (res < 0)
|
||||
+ return res;
|
||||
+
|
||||
+ cnt *= (stream->info.channels * stream->info.width);
|
||||
+ return cnt;
|
||||
+}
|
||||
+
|
||||
+static void S_OPUS_CodecCloseStream (snd_stream_t *stream)
|
||||
+{
|
||||
+ op_free((OggOpusFile *)stream->priv);
|
||||
+ S_CodecUtilClose(&stream);
|
||||
+}
|
||||
+
|
||||
+static int S_OPUS_CodecRewindStream (snd_stream_t *stream)
|
||||
+{
|
||||
+ return op_pcm_seek ((OggOpusFile *)stream->priv, 0);
|
||||
+}
|
||||
+
|
||||
+snd_codec_t opus_codec =
|
||||
+{
|
||||
+ CODECTYPE_OPUS,
|
||||
+ true, /* always available. */
|
||||
+ "opus",
|
||||
+ S_OPUS_CodecInitialize,
|
||||
+ S_OPUS_CodecShutdown,
|
||||
+ S_OPUS_CodecOpenStream,
|
||||
+ S_OPUS_CodecReadStream,
|
||||
+ S_OPUS_CodecRewindStream,
|
||||
+ S_OPUS_CodecCloseStream,
|
||||
+ NULL
|
||||
+};
|
||||
+
|
||||
+#endif /* USE_CODEC_OPUS */
|
||||
+
|
||||
Index: snd_opus.h
|
||||
===================================================================
|
||||
--- snd_opus.h (revision 0)
|
||||
+++ snd_opus.h (revision 0)
|
||||
@@ -0,0 +1,13 @@
|
||||
+/* Ogg/Opus streaming music support. */
|
||||
+
|
||||
+#if !defined(_SND_OPUS_H_)
|
||||
+#define _SND_OPUS_H_ 1
|
||||
+
|
||||
+#if defined(USE_CODEC_OPUS)
|
||||
+
|
||||
+extern snd_codec_t opus_codec;
|
||||
+
|
||||
+#endif /* USE_CODEC_OPUS */
|
||||
+
|
||||
+#endif /* ! _SND_OPUS_H_ */
|
||||
+
|
Loading…
Reference in a new issue