From 6b0fa20b8b40b7211b18129ebad108f314a0d5e0 Mon Sep 17 00:00:00 2001
From: Sergeanur <s.anureev@yandex.ua>
Date: Thu, 7 Jan 2021 22:01:44 +0200
Subject: [PATCH] Make opus available alongside other formats

---
 src/audio/oal/stream.cpp  | 130 +++++++++++++++++++-------------------
 src/audio/sampman.h       |   8 +--
 src/audio/sampman_oal.cpp |  12 ++--
 src/core/config.h         |  14 +++-
 4 files changed, 88 insertions(+), 76 deletions(-)

diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp
index cdf063fa..32ce9537 100644
--- a/src/audio/oal/stream.cpp
+++ b/src/audio/oal/stream.cpp
@@ -4,20 +4,23 @@
 #include "stream.h"
 #include "sampman.h"
 
-#ifdef AUDIO_OPUS
-#include <opusfile.h>
-#else
 #ifdef _WIN32
 #ifdef AUDIO_OAL_USE_SNDFILE
 #pragma comment( lib, "libsndfile-1.lib" )
 #endif
+#ifdef AUDIO_OAL_USE_MPG123
 #pragma comment( lib, "libmpg123-0.lib" )
 #endif
+#endif
 #ifdef AUDIO_OAL_USE_SNDFILE
 #include <sndfile.h>
 #endif
+#ifdef AUDIO_OAL_USE_MPG123
 #include <mpg123.h>
 #endif
+#ifdef AUDIO_OAL_USE_OPUS
+#include <opusfile.h>
+#endif
 
 #ifndef _WIN32
 #include "crossplatform.h"
@@ -81,7 +84,6 @@ public:
 
 CSortStereoBuffer SortStereoBuffer;
 
-#ifndef AUDIO_OPUS
 class CImaADPCMDecoder
 {
 	const uint16 StepTable[89] = {
@@ -461,11 +463,9 @@ public:
 };
 #endif
 
-#ifdef _WIN32
+#ifdef AUDIO_OAL_USE_MPG123
 // fuzzy seek eliminates stutter when playing ADF but spams errors a lot (nothing breaks though)
 #define MP3_USE_FUZZY_SEEK
-#endif // _WIN32
-
 
 class CMP3File : public IDecoder
 {
@@ -574,6 +574,55 @@ public:
 	}
 };
 
+class CADFFile : public CMP3File
+{
+	static ssize_t r_read(void* fh, void* buf, size_t size)
+	{
+		size_t bytesRead = fread(buf, 1, size, (FILE*)fh);
+		uint8* _buf = (uint8*)buf;
+		for (size_t i = 0; i < size; i++)
+			_buf[i] ^= 0x22;
+		return bytesRead;
+	}
+	static off_t r_seek(void* fh, off_t pos, int seekType)
+	{
+		fseek((FILE*)fh, pos, seekType);
+		return ftell((FILE*)fh);
+	}
+	static void r_close(void* fh)
+	{
+		fclose((FILE*)fh);
+	}
+public:
+	CADFFile(const char* path)
+	{
+		m_pMH = mpg123_new(nil, nil);
+		if (m_pMH)
+		{
+#ifdef MP3_USE_FUZZY_SEEK
+			mpg123_param(m_pMH, MPG123_FLAGS, MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS | MPG123_QUIET, 0.0);
+#endif
+			long rate = 0;
+			int channels = 0;
+			int encoding = 0;
+
+			FILE* f = fopen(path, "rb");
+
+			m_bOpened = mpg123_replace_reader_handle(m_pMH, r_read, r_seek, r_close) == MPG123_OK
+				&& mpg123_open_handle(m_pMH, f) == MPG123_OK &&  mpg123_getformat(m_pMH, &rate, &channels, &encoding) == MPG123_OK;
+			m_nRate = rate;
+			m_nChannels = channels;
+
+			if (IsOpened())
+			{
+				mpg123_format_none(m_pMH);
+				mpg123_format(m_pMH, rate, channels, encoding);
+			}
+		}
+	}
+};
+
+#endif
 #define VAG_LINE_SIZE (0x10)
 #define VAG_SAMPLES_IN_LINE (28)
 
@@ -811,7 +860,7 @@ public:
 		return bufSizePerChannel * m_nChannels;
 	}
 };
-#else
+#ifdef AUDIO_OAL_USE_OPUS
 class COpusFile : public IDecoder
 {
 	OggOpusFile *m_FileH;
@@ -907,64 +956,16 @@ public:
 };
 #endif
 
-class CADFFile : public CMP3File
-{
-	static ssize_t r_read(void* fh, void* buf, size_t size)
-	{
-		size_t bytesRead = fread(buf, 1, size, (FILE*)fh);
-		uint8* _buf = (uint8*)buf;
-		for (size_t i = 0; i < size; i++)
-			_buf[i] ^= 0x22;
-		return bytesRead;
-	}
-	static off_t r_seek(void* fh, off_t pos, int seekType)
-	{
-		fseek((FILE*)fh, pos, seekType);
-		return ftell((FILE*)fh);
-	}
-	static void r_close(void* fh)
-	{
-		fclose((FILE*)fh);
-	}
-public:
-	CADFFile(const char* path)
-	{
-		m_pMH = mpg123_new(nil, nil);
-		if (m_pMH)
-		{
-#ifdef MP3_USE_FUZZY_SEEK
-			mpg123_param(m_pMH, MPG123_FLAGS, MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS, 0.0);
-#endif
-			long rate = 0;
-			int channels = 0;
-			int encoding = 0;
-
-			FILE* f = fopen(path, "rb");
-
-			m_bOpened = mpg123_replace_reader_handle(m_pMH, r_read, r_seek, r_close) == MPG123_OK
-				&& mpg123_open_handle(m_pMH, f) == MPG123_OK &&  mpg123_getformat(m_pMH, &rate, &channels, &encoding) == MPG123_OK;
-			m_nRate = rate;
-			m_nChannels = channels;
-
-			if (IsOpened())
-			{
-				mpg123_format_none(m_pMH);
-				mpg123_format(m_pMH, rate, channels, encoding);
-			}
-		}
-	}
-};
-
 void CStream::Initialise()
 {
-#ifndef AUDIO_OPUS
+#ifdef AUDIO_OAL_USE_MPG123
 	mpg123_init();
 #endif
 }
 
 void CStream::Terminate()
 {
-#ifndef AUDIO_OPUS
+#ifdef AUDIO_OAL_USE_MPG123
 	mpg123_exit();
 #endif
 }
@@ -997,21 +998,22 @@ CStream::CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBU
 		
 	DEV("Stream %s\n", m_aFilename);
 
-#ifndef AUDIO_OPUS
-	if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".mp3")], ".mp3"))
-		m_pSoundFile = new CMP3File(m_aFilename);
-	else if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".wav")], ".wav"))
+	if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".wav")], ".wav"))
 #ifdef AUDIO_OAL_USE_SNDFILE
 		m_pSoundFile = new CSndFile(m_aFilename);
 #else
 		m_pSoundFile = new CWavFile(m_aFilename);
 #endif
+#ifdef AUDIO_OAL_USE_MPG123
+	else if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".mp3")], ".mp3"))
+		m_pSoundFile = new CMP3File(m_aFilename);
 	else if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".adf")], ".adf"))
 		m_pSoundFile = new CADFFile(m_aFilename);
+#endif
 	else if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".vb")], ".VB"))
 		m_pSoundFile = new CVbFile(m_aFilename, overrideSampleRate);
-#else
-	if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".opus")], ".opus"))
+#ifdef AUDIO_OAL_USE_OPUS
+	else if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".opus")], ".opus"))
 		m_pSoundFile = new COpusFile(m_aFilename);
 #endif
 	else 
diff --git a/src/audio/sampman.h b/src/audio/sampman.h
index d3e4415f..2db29244 100644
--- a/src/audio/sampman.h
+++ b/src/audio/sampman.h
@@ -240,7 +240,7 @@ public:
 extern cSampleManager SampleManager;
 extern uint32 BankStartOffset[MAX_SFX_BANKS];
 
-#ifdef AUDIO_OPUS
+#if defined(OPUS_AUDIO_PATHS)
 static char StreamedNameTable[][25] = {
     "AUDIO\\HEAD.OPUS",    "AUDIO\\CLASS.OPUS",   "AUDIO\\KJAH.OPUS",    "AUDIO\\RISE.OPUS",    "AUDIO\\LIPS.OPUS",    "AUDIO\\GAME.OPUS",
     "AUDIO\\MSX.OPUS",     "AUDIO\\FLASH.OPUS",   "AUDIO\\CHAT.OPUS",    "AUDIO\\HEAD.OPUS",    "AUDIO\\POLICE.OPUS",  "AUDIO\\CITY.OPUS",
@@ -275,8 +275,7 @@ static char StreamedNameTable[][25] = {
     "AUDIO\\h5_b.OPUS",    "AUDIO\\h5_c.OPUS",    "AUDIO\\ammu_a.OPUS",  "AUDIO\\ammu_b.OPUS",  "AUDIO\\ammu_c.OPUS",  "AUDIO\\door_1.OPUS",
     "AUDIO\\door_2.OPUS",  "AUDIO\\door_3.OPUS",  "AUDIO\\door_4.OPUS",  "AUDIO\\door_5.OPUS",  "AUDIO\\door_6.OPUS",  "AUDIO\\t3_a.OPUS",
     "AUDIO\\t3_b.OPUS",    "AUDIO\\t3_c.OPUS",    "AUDIO\\k1_b.OPUS",    "AUDIO\\cat1.OPUS"};
-#else
-#ifdef PS2_AUDIO
+#elif defined(PS2_AUDIO_PATHS)
 static char StreamedNameTable[][40] =
 {
 	"AUDIO\\MUSIC\\WILD.VB",
@@ -1610,5 +1609,4 @@ static char StreamedNameTable[][25] =
 	"AUDIO\\BUST_26.WAV",
 	"AUDIO\\BUST_27.WAV",
 	"AUDIO\\BUST_28.WAV",
-};
-#endif
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp
index 0d82d552..ce6458e6 100644
--- a/src/audio/sampman_oal.cpp
+++ b/src/audio/sampman_oal.cpp
@@ -30,7 +30,7 @@
 #include "MusicManager.h"
 #include "Frontend.h"
 #include "Timer.h"
-#ifdef AUDIO_OPUS
+#ifdef AUDIO_OAL_USE_OPUS
 #include <opusfile.h>
 #endif
 
@@ -83,7 +83,7 @@ char SampleBankDescFilename[] = "audio/sfx.SDT";
 char SampleBankDataFilename[] = "audio/sfx.RAW";
 
 FILE *fpSampleDescHandle;
-#ifdef AUDIO_OPUS
+#ifdef OPUS_SFX
 OggOpusFile *fpSampleDataHandle;
 #else
 FILE *fpSampleDataHandle;
@@ -1245,7 +1245,7 @@ cSampleManager::LoadSampleBank(uint8 nBank)
 		return false;
 	}
 	
-#ifdef AUDIO_OPUS
+#ifdef OPUS_SFX
 	int samplesRead = 0;
 	int samplesSize = nSampleBankSize[nBank] / 2;
 	op_pcm_seek(fpSampleDataHandle, 0);
@@ -1350,7 +1350,7 @@ cSampleManager::LoadPedComment(uint32 nComment)
 		}
 	}
 
-#ifdef AUDIO_OPUS
+#ifdef OPUS_SFX
 	int samplesRead = 0;
 	int samplesSize = m_aSamples[nComment].nSize / 2;
 	op_pcm_seek(fpSampleDataHandle, m_aSamples[nComment].nOffset / 2);
@@ -2007,7 +2007,7 @@ cSampleManager::InitialiseSampleBanks(void)
 	fpSampleDescHandle = fcaseopen(SampleBankDescFilename, "rb");
 	if ( fpSampleDescHandle == NULL )
 		return false;
-#ifndef AUDIO_OPUS
+#ifndef OPUS_SFX
 	fpSampleDataHandle = fcaseopen(SampleBankDataFilename, "rb");
 	if ( fpSampleDataHandle == NULL )
 	{
@@ -2025,7 +2025,7 @@ cSampleManager::InitialiseSampleBanks(void)
 	fpSampleDataHandle = op_open_file(SampleBankDataFilename, &e);
 #endif
 	fread(m_aSamples, sizeof(tSample), TOTAL_AUDIO_SAMPLES, fpSampleDescHandle);
-#ifdef AUDIO_OPUS
+#ifdef OPUS_SFX
 	int32 _nSampleDataEndOffset = m_aSamples[TOTAL_AUDIO_SAMPLES - 1].nOffset + m_aSamples[TOTAL_AUDIO_SAMPLES - 1].nSize;
 #endif
 	fclose(fpSampleDescHandle);
diff --git a/src/core/config.h b/src/core/config.h
index a06ed1be..874ff39a 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -364,9 +364,21 @@ static_assert(false, "SUPPORT_XBOX_SCRIPT and SUPPORT_MOBILE_SCRIPT are mutually
 
 // Audio
 #define AUDIO_CACHE // cache sound lengths to speed up the cold boot
-//#define PS2_AUDIO   // changes audio paths for cutscenes and radio to PS2 paths, needs vbdec to support VB with MSS
+//#define PS2_AUDIO_PATHS // changes audio paths for cutscenes and radio to PS2 paths (needs vbdec on MSS builds)
 //#define AUDIO_OAL_USE_SNDFILE // use libsndfile to decode WAVs instead of our internal decoder
+#define AUDIO_OAL_USE_MPG123 // use mpg123 to support mp3 files
 
+#ifdef AUDIO_OPUS
+#define AUDIO_OAL_USE_OPUS // enable support of opus files
+//#define OPUS_AUDIO_PATHS // (not supported on VC yet) changes audio paths to opus paths (doesn't work if AUDIO_OAL_USE_OPUS isn't enabled)
+//#define OPUS_SFX  // enable if your sfx.raw is encoded with opus (doesn't work if AUDIO_OAL_USE_OPUS isn't enabled)
+
+#ifndef AUDIO_OAL_USE_OPUS
+#undef OPUS_AUDIO_PATHS
+#undef OPUS_SFX
+#endif
+
+#endif
 
 #ifdef LIBRW
 // these are not supported with librw yet