diff --git a/Linux/CodeBlocks/QuakeSpasm.cbp b/Linux/CodeBlocks/QuakeSpasm.cbp
index 511468db..5d9a3987 100644
--- a/Linux/CodeBlocks/QuakeSpasm.cbp
+++ b/Linux/CodeBlocks/QuakeSpasm.cbp
@@ -263,6 +263,10 @@
+
+
+
+
diff --git a/MacOSX/QuakeSpasm.xcodeproj/project.pbxproj b/MacOSX/QuakeSpasm.xcodeproj/project.pbxproj
index 89c09b17..fefd23f9 100644
--- a/MacOSX/QuakeSpasm.xcodeproj/project.pbxproj
+++ b/MacOSX/QuakeSpasm.xcodeproj/project.pbxproj
@@ -79,6 +79,11 @@
486577CD0D31A22A00E7920A /* snd_mix.c in Sources */ = {isa = PBXBuildFile; fileRef = 486577CA0D31A22A00E7920A /* snd_mix.c */; };
48728D2D0D3004A80004D61B /* net_dgrm.c in Sources */ = {isa = PBXBuildFile; fileRef = 48728D280D3004A70004D61B /* net_dgrm.c */; };
48728D2E0D3004A80004D61B /* net_loop.c in Sources */ = {isa = PBXBuildFile; fileRef = 48728D2A0D3004A80004D61B /* net_loop.c */; };
+ 4885A84C179740A0000EC703 /* snd_opus.c in Sources */ = {isa = PBXBuildFile; fileRef = 4885A84A179740A0000EC703 /* snd_opus.c */; };
+ 4885A84F179740CA000EC703 /* libopus.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4885A84D179740CA000EC703 /* libopus.dylib */; };
+ 4885A850179740CA000EC703 /* libopusfile.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4885A84E179740CA000EC703 /* libopusfile.dylib */; };
+ 4885A851179740D7000EC703 /* libopus.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4885A84D179740CA000EC703 /* libopus.dylib */; };
+ 4885A852179740D7000EC703 /* libopusfile.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4885A84E179740CA000EC703 /* libopusfile.dylib */; };
48895DB90D4914A000849ABF /* pl_osx.m in Sources */ = {isa = PBXBuildFile; fileRef = 48895DB80D4914A000849ABF /* pl_osx.m */; };
489D8D2F0D3A630D00AA4471 /* ScreenInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 489D8D2E0D3A630D00AA4471 /* ScreenInfo.m */; };
48A7C1FC14AA34940011B754 /* strlcat.c in Sources */ = {isa = PBXBuildFile; fileRef = 48A7C1FA14AA34940011B754 /* strlcat.c */; };
@@ -129,6 +134,8 @@
dstPath = "";
dstSubfolderSpec = 6;
files = (
+ 4885A851179740D7000EC703 /* libopus.dylib in CopyFiles */,
+ 4885A852179740D7000EC703 /* libopusfile.dylib in CopyFiles */,
48E2EC8615FB516600B8D476 /* libmad.dylib in CopyFiles */,
48E2EC8715FB516600B8D476 /* libogg.dylib in CopyFiles */,
48E2EC8815FB516600B8D476 /* libvorbis.dylib in CopyFiles */,
@@ -268,6 +275,10 @@
48728D290D3004A80004D61B /* net_dgrm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = net_dgrm.h; path = ../Quake/net_dgrm.h; sourceTree = SOURCE_ROOT; };
48728D2A0D3004A80004D61B /* net_loop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = net_loop.c; path = ../Quake/net_loop.c; sourceTree = SOURCE_ROOT; };
48728D2B0D3004A80004D61B /* net_loop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = net_loop.h; path = ../Quake/net_loop.h; sourceTree = SOURCE_ROOT; };
+ 4885A84A179740A0000EC703 /* snd_opus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = snd_opus.c; path = ../Quake/snd_opus.c; sourceTree = ""; };
+ 4885A84B179740A0000EC703 /* snd_opus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = snd_opus.h; path = ../Quake/snd_opus.h; sourceTree = ""; };
+ 4885A84D179740CA000EC703 /* libopus.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libopus.dylib; path = codecs/lib/libopus.dylib; sourceTree = ""; };
+ 4885A84E179740CA000EC703 /* libopusfile.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libopusfile.dylib; path = codecs/lib/libopusfile.dylib; sourceTree = ""; };
48895DB80D4914A000849ABF /* pl_osx.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = pl_osx.m; path = ../Quake/pl_osx.m; sourceTree = SOURCE_ROOT; };
488EF23614B83A370021DD41 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
489D8D2D0D3A630D00AA4471 /* ScreenInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScreenInfo.h; sourceTree = ""; };
@@ -299,6 +310,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 4885A84F179740CA000EC703 /* libopus.dylib in Frameworks */,
+ 4885A850179740CA000EC703 /* libopusfile.dylib in Frameworks */,
48E2EC7D15FB507A00B8D476 /* libmad.dylib in Frameworks */,
48E2EC7E15FB507A00B8D476 /* libogg.dylib in Frameworks */,
48E2EC7F15FB507A00B8D476 /* libvorbis.dylib in Frameworks */,
@@ -346,6 +359,8 @@
29B97314FDCFA39411CA2CEA /* QuakeSpasm */ = {
isa = PBXGroup;
children = (
+ 4885A84D179740CA000EC703 /* libopus.dylib */,
+ 4885A84E179740CA000EC703 /* libopusfile.dylib */,
48E2EC7915FB507A00B8D476 /* libmad.dylib */,
48E2EC7A15FB507A00B8D476 /* libogg.dylib */,
48E2EC7B15FB507A00B8D476 /* libvorbis.dylib */,
@@ -494,6 +509,7 @@
486577CA0D31A22A00E7920A /* snd_mix.c */,
483A78540D2EEAC300CB2E4C /* snd_sdl.c */,
4854B1B01340C646004C9F45 /* snd_mp3.c */,
+ 4885A84A179740A0000EC703 /* snd_opus.c */,
4818B0B212D5BA1A006DD66E /* snd_vorbis.c */,
4818B0B412D5BA1A006DD66E /* snd_wave.c */,
);
@@ -582,6 +598,7 @@
4818B0AD12D5B9ED006DD66E /* snd_codec.h */,
4818B0AF12D5BA1A006DD66E /* snd_codeci.h */,
4818B0B112D5BA1A006DD66E /* snd_mp3.h */,
+ 4885A84B179740A0000EC703 /* snd_opus.h */,
4818B0B312D5BA1A006DD66E /* snd_vorbis.h */,
4818B0B512D5BA1A006DD66E /* snd_wave.h */,
);
@@ -755,6 +772,7 @@
B021C20914A5FF7E003F18D6 /* cfgfile.c in Sources */,
48A7C1FC14AA34940011B754 /* strlcat.c in Sources */,
48A7C1FD14AA34940011B754 /* strlcpy.c in Sources */,
+ 4885A84C179740A0000EC703 /* snd_opus.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -839,6 +857,7 @@
USE_CODEC_MP3,
USE_CODEC_VORBIS,
USE_CODEC_WAVE,
+ USE_CODEC_OPUS,
USE_QS_CONBACK,
SDL_FRAMEWORK,
);
@@ -928,6 +947,7 @@
USE_CODEC_MP3,
USE_CODEC_VORBIS,
USE_CODEC_WAVE,
+ USE_CODEC_OPUS,
USE_QS_CONBACK,
SDL_FRAMEWORK,
);
diff --git a/Misc/snd_opus.patch b/Misc/snd_opus.patch
deleted file mode 100644
index 71869678..00000000
--- a/Misc/snd_opus.patch
+++ /dev/null
@@ -1,423 +0,0 @@
-Opus file decoding support. it is not enabled by default: just edit
-the Makefile for USE_CODEC_OPUS.
-
-2013.02.28 O.Sezer
-
-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 /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
-+ *
-+ * 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
-+#include
-+
-+
-+/* 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_ */
-+
diff --git a/Quake/Makefile b/Quake/Makefile
index 6ad9a724..30aa36ec 100644
--- a/Quake/Makefile
+++ b/Quake/Makefile
@@ -12,6 +12,7 @@ USE_QS_CONBACK=1
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 @@ CODECLIBS :=
ifeq ($(USE_CODEC_WAVE),1)
CFLAGS+= -DUSE_CODEC_WAVE
endif
+ifeq ($(USE_CODEC_OPUS),1)
+# opus and opusfile put their *.h under /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 @@ MUSIC_OBJS:= bgmusic.o \
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
diff --git a/Quake/Makefile.darwin b/Quake/Makefile.darwin
index fbd77814..19686b1f 100644
--- a/Quake/Makefile.darwin
+++ b/Quake/Makefile.darwin
@@ -13,6 +13,7 @@ USE_QS_CONBACK=1
USE_CODEC_WAVE=1
USE_CODEC_MP3=1
USE_CODEC_VORBIS=1
+USE_CODEC_OPUS=1
# which library to use for mp3 decoding: mad or mpg123
MP3LIB=mad
@@ -123,6 +124,12 @@ CODECLIBS :=
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 @@ MUSIC_OBJS:= bgmusic.o \
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
diff --git a/Quake/Makefile.w32 b/Quake/Makefile.w32
index 0d836e93..27b3e173 100644
--- a/Quake/Makefile.w32
+++ b/Quake/Makefile.w32
@@ -13,6 +13,7 @@ USE_QS_CONBACK=1
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 @@ CFLAGS+= -DUSE_CODEC_WAVE
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 @@ MUSIC_OBJS:= bgmusic.o \
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
diff --git a/Quake/Makefile.w64 b/Quake/Makefile.w64
index b67e06fa..69eb3794 100644
--- a/Quake/Makefile.w64
+++ b/Quake/Makefile.w64
@@ -13,6 +13,7 @@ USE_QS_CONBACK=1
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 @@ CFLAGS+= -DUSE_CODEC_WAVE
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 @@ MUSIC_OBJS:= bgmusic.o \
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
diff --git a/Quake/bgmusic.c b/Quake/bgmusic.c
index bc28cf96..7763afb8 100644
--- a/Quake/bgmusic.c
+++ b/Quake/bgmusic.c
@@ -54,6 +54,7 @@ typedef struct music_handler_s
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 },
diff --git a/Quake/snd_codec.c b/Quake/snd_codec.c
index 00beca11..9132a185 100644
--- a/Quake/snd_codec.c
+++ b/Quake/snd_codec.c
@@ -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;
@@ -66,6 +67,9 @@ void S_CodecInit (void)
#endif
#ifdef USE_CODEC_VORBIS
S_CodecRegister(&vorbis_codec);
+#endif
+#ifdef USE_CODEC_OPUS
+ S_CodecRegister(&opus_codec);
#endif
codec = codecs;
while (codec)
diff --git a/Quake/snd_codec.h b/Quake/snd_codec.h
index 1cab64a1..f7580599 100644
--- a/Quake/snd_codec.h
+++ b/Quake/snd_codec.h
@@ -88,6 +88,7 @@ void S_CodecUtilClose(snd_stream_t **stream);
#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
diff --git a/Quake/snd_opus.c b/Quake/snd_opus.c
new file mode 100644
index 00000000..c901ae2c
--- /dev/null
+++ b/Quake/snd_opus.c
@@ -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
+ *
+ * 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
+#include
+
+
+/* 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 */
+
diff --git a/Quake/snd_opus.h b/Quake/snd_opus.h
new file mode 100644
index 00000000..4c2a25fe
--- /dev/null
+++ b/Quake/snd_opus.h
@@ -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_ */
+
diff --git a/Windows/CodeBlocks/QuakeSpasm.cbp b/Windows/CodeBlocks/QuakeSpasm.cbp
index 42fb7b49..7cb4c6ba 100644
--- a/Windows/CodeBlocks/QuakeSpasm.cbp
+++ b/Windows/CodeBlocks/QuakeSpasm.cbp
@@ -36,6 +36,7 @@
+
@@ -44,6 +45,8 @@
+
+
@@ -272,6 +275,10 @@
+
+
+
+
diff --git a/Windows/VisualStudio/quakespasm.vcproj b/Windows/VisualStudio/quakespasm.vcproj
index 80daf26e..e456937c 100644
--- a/Windows/VisualStudio/quakespasm.vcproj
+++ b/Windows/VisualStudio/quakespasm.vcproj
@@ -41,7 +41,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="C:\SDL\include;..\codecs\include;..\..\Quake;.;.."
- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_QS_CONBACK;USE_CODEC_MP3;USE_CODEC_VORBIS;USE_CODEC_WAVE"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_QS_CONBACK;USE_CODEC_MP3;USE_CODEC_VORBIS;USE_CODEC_WAVE;USE_CODEC_OPUS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
@@ -61,7 +61,7 @@
/>
+
+
@@ -819,6 +823,10 @@
RelativePath="..\..\Quake\snd_mp3.h"
>
+
+