summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergeanur <s.anureev@yandex.ua>2020-05-22 17:40:19 +0300
committerSergeanur <s.anureev@yandex.ua>2020-05-22 17:40:19 +0300
commit0af4d57408842d501af2fce4617e19a3bf9466eb (patch)
treeecef62ff91adfd2a437f16b592f2184d89cc0ba7
parentaba523d14e16d5bcca0e29f29ad9ecf3562093cf (diff)
opus support
-rw-r--r--premake5.lua29
-rw-r--r--src/audio/oal/stream.cpp110
-rw-r--r--src/audio/sampman.h37
-rw-r--r--src/audio/sampman_oal.cpp64
4 files changed, 235 insertions, 5 deletions
diff --git a/premake5.lua b/premake5.lua
index c8494884..c6551a21 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -17,6 +17,11 @@ newoption {
description = "Build and use librw from this solution"
}
+newoption {
+ trigger = "with-opus",
+ description = "Build with opus"
+}
+
if(_OPTIONS["with-librw"]) then
Librw = "librw"
else
@@ -185,8 +190,25 @@ project "re3"
includedirs { "milessdk/include" }
includedirs { "eax" }
+
+ includedirs { "openal-soft/include" }
+ includedirs { "mpg123/include" }
+ includedirs { "libsndfile/include" }
+ includedirs { "ogg/include" }
+ includedirs { "opus/include" }
+ includedirs { "opusfile/include" }
libdirs { "milessdk/lib" }
+ libdirs { "openal-soft/libs/Win32" }
+ libdirs { "mpg123/lib" }
+ libdirs { "libsndfile/lib" }
+ if _OPTIONS["with-opus"] then
+ filter "platforms:win*"
+ libdirs { "ogg/win32/VS2015/Win32/%{cfg.buildcfg}" }
+ libdirs { "opus/win32/VS2015/Win32/%{cfg.buildcfg}" }
+ libdirs { "opusfile/win32/VS2015/Win32/Release-NoHTTP" }
+ filter {}
+ end
if(os.getenv("GTA_III_RE_DIR")) then
setpaths("$(GTA_III_RE_DIR)/", "%(cfg.buildtarget.name)", "")
@@ -202,6 +224,13 @@ project "re3"
filter "platforms:linux*"
defines { "OPENAL" }
links { "openal", "mpg123", "sndfile", "pthread" }
+
+ if _OPTIONS["with-opus"] then
+ filter {}
+ links { "libogg" }
+ links { "opus" }
+ links { "opusfile" }
+ end
filter "platforms:*RW33*"
staticruntime "on"
diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp
index 5a9c7d7d..21e4d8c6 100644
--- a/src/audio/oal/stream.cpp
+++ b/src/audio/oal/stream.cpp
@@ -4,8 +4,9 @@
#include "common.h"
#include "sampman.h"
-#include <sndfile.h>
-#include <mpg123.h>
+#ifdef AUDIO_OPUS
+#include <opusfile.h>
+#else
#ifdef _WIN32
typedef long ssize_t;
#pragma comment( lib, "libsndfile-1.lib" )
@@ -13,7 +14,11 @@ typedef long ssize_t;
#else
#include "crossplatform.h"
#endif
+#include <sndfile.h>
+#include <mpg123.h>
+#endif
+#ifndef AUDIO_OPUS
class CSndFile : public IDecoder
{
SNDFILE *m_pfSound;
@@ -170,15 +175,111 @@ public:
return size;
}
};
+#else
+class COpusFile : public IDecoder
+{
+ OggOpusFile *m_FileH;
+ bool m_bOpened;
+ uint32 m_nRate;
+ uint32 m_nChannels;
+public:
+ _declspec(noinline) COpusFile(const char *path) : m_FileH(nil),
+ m_bOpened(false),
+ m_nRate(0),
+ m_nChannels(0)
+ {
+ int ret;
+ m_FileH = op_open_file(path, &ret);
+
+ if (m_FileH) {
+ m_nChannels = op_head(m_FileH, 0)->channel_count;
+ m_nRate = op_head(m_FileH, 0)->input_sample_rate;
+ auto tags = op_tags(m_FileH, 0);
+ for (int i = 0; i < tags->comments; i++) {
+ if (strncmp(tags->user_comments[i], "SAMPLERATE", sizeof("SAMPLERATE")-1) == 0)
+ {
+ sscanf(tags->user_comments[i], "SAMPLERATE=%i", &m_nRate);
+ break;
+ }
+ }
+
+ m_bOpened = true;
+ }
+ }
+
+ ~COpusFile()
+ {
+ if (m_FileH)
+ {
+ op_free(m_FileH);
+ m_FileH = nil;
+ }
+ }
+
+ bool IsOpened()
+ {
+ return m_bOpened;
+ }
+
+ uint32 GetSampleSize()
+ {
+ return sizeof(uint16);
+ }
+
+ uint32 GetSampleCount()
+ {
+ if ( !IsOpened() ) return 0;
+ return op_pcm_total(m_FileH, 0);
+ }
+
+ uint32 GetSampleRate()
+ {
+ return m_nRate;
+ }
+
+ uint32 GetChannels()
+ {
+ return m_nChannels;
+ }
+
+ void Seek(uint32 milliseconds)
+ {
+ if ( !IsOpened() ) return;
+ op_pcm_seek(m_FileH, ms2samples(milliseconds) * GetSampleSize());
+ }
+
+ uint32 Tell()
+ {
+ if ( !IsOpened() ) return 0;
+ return samples2ms(op_pcm_tell(m_FileH)/GetSampleSize());
+ }
+
+ uint32 Decode(void *buffer)
+ {
+ if ( !IsOpened() ) return 0;
+
+ int size = op_read(m_FileH, (opus_int16 *)buffer, GetBufferSamples(), NULL);
+
+ if (size < 0)
+ return 0;
+
+ return size * m_nChannels * GetSampleSize();
+ }
+};
+#endif
void CStream::Initialise()
{
+#ifndef AUDIO_OPUS
mpg123_init();
+#endif
}
void CStream::Terminate()
{
+#ifndef AUDIO_OPUS
mpg123_exit();
+#endif
}
CStream::CStream(char *filename, ALuint &source, ALuint (&buffers)[NUM_STREAMBUFFERS]) :
@@ -213,10 +314,15 @@ CStream::CStream(char *filename, ALuint &source, ALuint (&buffers)[NUM_STREAMBUF
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"))
m_pSoundFile = new CSndFile(m_aFilename);
+#else
+ if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(".opus")], ".opus"))
+ m_pSoundFile = new COpusFile(m_aFilename);
+#endif
else
m_pSoundFile = nil;
ASSERT(m_pSoundFile != nil);
diff --git a/src/audio/sampman.h b/src/audio/sampman.h
index d3c82943..3eeff476 100644
--- a/src/audio/sampman.h
+++ b/src/audio/sampman.h
@@ -144,6 +144,42 @@ public:
extern cSampleManager SampleManager;
extern uint32 BankStartOffset[MAX_SAMPLEBANKS];
+#ifdef AUDIO_OPUS
+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",
+ "AUDIO\\WATER.OPUS", "AUDIO\\COMOPEN.OPUS", "AUDIO\\SUBOPEN.OPUS", "AUDIO\\JB.OPUS", "AUDIO\\BET.OPUS", "AUDIO\\L1_LG.OPUS",
+ "AUDIO\\L2_DSB.OPUS", "AUDIO\\L3_DM.OPUS", "AUDIO\\L4_PAP.OPUS", "AUDIO\\L5_TFB.OPUS", "AUDIO\\J0_DM2.OPUS", "AUDIO\\J1_LFL.OPUS",
+ "AUDIO\\J2_KCL.OPUS", "AUDIO\\J3_VH.OPUS", "AUDIO\\J4_ETH.OPUS", "AUDIO\\J5_DST.OPUS", "AUDIO\\J6_TBJ.OPUS", "AUDIO\\T1_TOL.OPUS",
+ "AUDIO\\T2_TPU.OPUS", "AUDIO\\T3_MAS.OPUS", "AUDIO\\T4_TAT.OPUS", "AUDIO\\T5_BF.OPUS", "AUDIO\\S0_MAS.OPUS", "AUDIO\\S1_PF.OPUS",
+ "AUDIO\\S2_CTG.OPUS", "AUDIO\\S3_RTC.OPUS", "AUDIO\\S5_LRQ.OPUS", "AUDIO\\S4_BDBA.OPUS", "AUDIO\\S4_BDBB.OPUS", "AUDIO\\S2_CTG2.OPUS",
+ "AUDIO\\S4_BDBD.OPUS", "AUDIO\\S5_LRQB.OPUS", "AUDIO\\S5_LRQC.OPUS", "AUDIO\\A1_SSO.OPUS", "AUDIO\\A2_PP.OPUS", "AUDIO\\A3_SS.OPUS",
+ "AUDIO\\A4_PDR.OPUS", "AUDIO\\A5_K2FT.OPUS", "AUDIO\\K1_KBO.OPUS", "AUDIO\\K2_GIS.OPUS", "AUDIO\\K3_DS.OPUS", "AUDIO\\K4_SHI.OPUS",
+ "AUDIO\\K5_SD.OPUS", "AUDIO\\R0_PDR2.OPUS", "AUDIO\\R1_SW.OPUS", "AUDIO\\R2_AP.OPUS", "AUDIO\\R3_ED.OPUS", "AUDIO\\R4_GF.OPUS",
+ "AUDIO\\R5_PB.OPUS", "AUDIO\\R6_MM.OPUS", "AUDIO\\D1_STOG.OPUS", "AUDIO\\D2_KK.OPUS", "AUDIO\\D3_ADO.OPUS", "AUDIO\\D5_ES.OPUS",
+ "AUDIO\\D7_MLD.OPUS", "AUDIO\\D4_GTA.OPUS", "AUDIO\\D4_GTA2.OPUS", "AUDIO\\D6_STS.OPUS", "AUDIO\\A6_BAIT.OPUS", "AUDIO\\A7_ETG.OPUS",
+ "AUDIO\\A8_PS.OPUS", "AUDIO\\A9_ASD.OPUS", "AUDIO\\K4_SHI2.OPUS", "AUDIO\\C1_TEX.OPUS", "AUDIO\\EL_PH1.OPUS", "AUDIO\\EL_PH2.OPUS",
+ "AUDIO\\EL_PH3.OPUS", "AUDIO\\EL_PH4.OPUS", "AUDIO\\YD_PH1.OPUS", "AUDIO\\YD_PH2.OPUS", "AUDIO\\YD_PH3.OPUS", "AUDIO\\YD_PH4.OPUS",
+ "AUDIO\\HD_PH1.OPUS", "AUDIO\\HD_PH2.OPUS", "AUDIO\\HD_PH3.OPUS", "AUDIO\\HD_PH4.OPUS", "AUDIO\\HD_PH5.OPUS", "AUDIO\\MT_PH1.OPUS",
+ "AUDIO\\MT_PH2.OPUS", "AUDIO\\MT_PH3.OPUS", "AUDIO\\MT_PH4.OPUS", "AUDIO\\MISCOM.OPUS", "AUDIO\\END.OPUS", "AUDIO\\lib_a1.OPUS",
+ "AUDIO\\lib_a2.OPUS", "AUDIO\\lib_a.OPUS", "AUDIO\\lib_b.OPUS", "AUDIO\\lib_c.OPUS", "AUDIO\\lib_d.OPUS", "AUDIO\\l2_a.OPUS",
+ "AUDIO\\j4t_1.OPUS", "AUDIO\\j4t_2.OPUS", "AUDIO\\j4t_3.OPUS", "AUDIO\\j4t_4.OPUS", "AUDIO\\j4_a.OPUS", "AUDIO\\j4_b.OPUS",
+ "AUDIO\\j4_c.OPUS", "AUDIO\\j4_d.OPUS", "AUDIO\\j4_e.OPUS", "AUDIO\\j4_f.OPUS", "AUDIO\\j6_1.OPUS", "AUDIO\\j6_a.OPUS",
+ "AUDIO\\j6_b.OPUS", "AUDIO\\j6_c.OPUS", "AUDIO\\j6_d.OPUS", "AUDIO\\t4_a.OPUS", "AUDIO\\s1_a.OPUS", "AUDIO\\s1_a1.OPUS",
+ "AUDIO\\s1_b.OPUS", "AUDIO\\s1_c.OPUS", "AUDIO\\s1_c1.OPUS", "AUDIO\\s1_d.OPUS", "AUDIO\\s1_e.OPUS", "AUDIO\\s1_f.OPUS",
+ "AUDIO\\s1_g.OPUS", "AUDIO\\s1_h.OPUS", "AUDIO\\s1_i.OPUS", "AUDIO\\s1_j.OPUS", "AUDIO\\s1_k.OPUS", "AUDIO\\s1_l.OPUS",
+ "AUDIO\\s3_a.OPUS", "AUDIO\\s3_b.OPUS", "AUDIO\\el3_a.OPUS", "AUDIO\\mf1_a.OPUS", "AUDIO\\mf2_a.OPUS", "AUDIO\\mf3_a.OPUS",
+ "AUDIO\\mf3_b.OPUS", "AUDIO\\mf3_b1.OPUS", "AUDIO\\mf3_c.OPUS", "AUDIO\\mf4_a.OPUS", "AUDIO\\mf4_b.OPUS", "AUDIO\\mf4_c.OPUS",
+ "AUDIO\\a1_a.OPUS", "AUDIO\\a3_a.OPUS", "AUDIO\\a5_a.OPUS", "AUDIO\\a4_a.OPUS", "AUDIO\\a4_b.OPUS", "AUDIO\\a4_c.OPUS",
+ "AUDIO\\a4_d.OPUS", "AUDIO\\k1_a.OPUS", "AUDIO\\k3_a.OPUS", "AUDIO\\r1_a.OPUS", "AUDIO\\r2_a.OPUS", "AUDIO\\r2_b.OPUS",
+ "AUDIO\\r2_c.OPUS", "AUDIO\\r2_d.OPUS", "AUDIO\\r2_e.OPUS", "AUDIO\\r2_f.OPUS", "AUDIO\\r2_g.OPUS", "AUDIO\\r2_h.OPUS",
+ "AUDIO\\r5_a.OPUS", "AUDIO\\r6_a.OPUS", "AUDIO\\r6_a1.OPUS", "AUDIO\\r6_b.OPUS", "AUDIO\\lo2_a.OPUS", "AUDIO\\lo6_a.OPUS",
+ "AUDIO\\yd2_a.OPUS", "AUDIO\\yd2_b.OPUS", "AUDIO\\yd2_c.OPUS", "AUDIO\\yd2_c1.OPUS", "AUDIO\\yd2_d.OPUS", "AUDIO\\yd2_e.OPUS",
+ "AUDIO\\yd2_f.OPUS", "AUDIO\\yd2_g.OPUS", "AUDIO\\yd2_h.OPUS", "AUDIO\\yd2_ass.OPUS", "AUDIO\\yd2_ok.OPUS", "AUDIO\\h5_a.OPUS",
+ "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
static char StreamedNameTable[][25]=
{
"AUDIO\\HEAD.WAV",
@@ -343,3 +379,4 @@ static char StreamedNameTable[][25]=
"AUDIO\\k1_b.WAV",
"AUDIO\\cat1.WAV"
};
+#endif \ No newline at end of file
diff --git a/src/audio/sampman_oal.cpp b/src/audio/sampman_oal.cpp
index 30efd7f5..d8d7ac24 100644
--- a/src/audio/sampman_oal.cpp
+++ b/src/audio/sampman_oal.cpp
@@ -27,6 +27,9 @@
#include "MusicManager.h"
#include "Frontend.h"
#include "Timer.h"
+#ifdef AUDIO_OPUS
+#include <opusfile.h>
+#endif
//TODO: fix eax3 reverb
//TODO: max channals
@@ -42,6 +45,10 @@ bool _bSampmanInitialised = false;
uint32 BankStartOffset[MAX_SAMPLEBANKS];
+#ifdef AUDIO_OPUS
+OggOpusFile *opusSFX;
+#endif
+
int prevprovider=-1;
int curprovider=-1;
int usingEAX=0;
@@ -444,6 +451,8 @@ int8 cSampleManager::GetCurrent3DProviderIndex(void)
int8 cSampleManager::SetCurrent3DProvider(uint8 nProvider)
{
ASSERT( nProvider < m_nNumberOfProviders );
+ if (nProvider >= m_nNumberOfProviders)
+ nProvider = 0;
int savedprovider = curprovider;
if ( nProvider < m_nNumberOfProviders )
@@ -743,12 +752,37 @@ cSampleManager::LoadSampleBank(uint8 nBank)
return false;
}
+#ifdef AUDIO_OPUS
+ int ret;
+ //OggOpusFile *file = op_open_file("AUDIO/SFX0.RAW", &ret);
+ int samplesRead = 0;
+ int samplesSize = nSampleBankSize[nBank] / 2;
+ op_pcm_seek(opusSFX, 0);
+ while (samplesSize > 0) {
+ int size = op_read(opusSFX, (opus_int16 *)(nSampleBankMemoryStartAddress[nBank] + samplesRead), samplesSize, NULL);
+ if (size <= 0) {
+ // huh?
+ //assert(0);
+ break;
+ }
+ samplesRead += size*2;
+ samplesSize -= size;
+ }
+ //op_free(file);
+
+ //if (samplesRead != nSampleBankSize[nBank])
+ // return false;
+
+ //FILE *fsd = fopen("sfx.temp", "wb");
+ //fwrite((void *)nSampleBankMemoryStartAddress[nBank], 1, nSampleBankSize[nBank], fsd);
+ //fclose(fsd);
+#else
if ( fseek(fpSampleDataHandle, nSampleBankDiscStartOffset[nBank], SEEK_SET) != 0 )
return false;
if ( fread((void *)nSampleBankMemoryStartAddress[nBank], 1, nSampleBankSize[nBank], fpSampleDataHandle) != nSampleBankSize[nBank] )
return false;
-
+#endif
bSampleBankLoaded[nBank] = true;
return true;
@@ -836,13 +870,28 @@ cSampleManager::LoadPedComment(uint32 nComment)
}
}
}
-
+
+#ifdef AUDIO_OPUS
+ int samplesRead = 0;
+ int samplesSize = m_aSamples[nComment].nSize / 2;
+ op_pcm_seek(opusSFX, m_aSamples[nComment].nOffset / 2);
+ while (samplesSize > 0) {
+ int size =
+ op_read(opusSFX, (opus_int16 *)(nSampleBankMemoryStartAddress[SAMPLEBANK_PED] + PED_BLOCKSIZE * nCurrentPedSlot + samplesRead), samplesSize, NULL);
+ if (size <= 0) {
+ return false;
+ }
+ samplesRead += size * 2;
+ samplesSize -= size;
+ }
+#else
if ( fseek(fpSampleDataHandle, m_aSamples[nComment].nOffset, SEEK_SET) != 0 )
return false;
if ( fread((void *)(nSampleBankMemoryStartAddress[SAMPLEBANK_PED] + PED_BLOCKSIZE*nCurrentPedSlot), 1, m_aSamples[nComment].nSize, fpSampleDataHandle) != m_aSamples[nComment].nSize )
return false;
-
+
+#endif
nPedSlotSfx[nCurrentPedSlot] = nComment;
alBufferData(pedBuffers[nCurrentPedSlot],
@@ -1406,6 +1455,15 @@ cSampleManager::InitialiseSampleBanks(void)
nSampleBankSize[SAMPLEBANK_MAIN] = nSampleBankDiscStartOffset[SAMPLEBANK_PED] - nSampleBankDiscStartOffset[SAMPLEBANK_MAIN];
nSampleBankSize[SAMPLEBANK_PED] = _nSampleDataEndOffset - nSampleBankDiscStartOffset[SAMPLEBANK_PED];
+ //int error = 0;
+ //auto encoder = opus_encoder_create(48000, 1, OPUS_APPLICATION_AUDIO, &error);
+ //error = opus_encoder_ctl(encoder, OPUS_SET_BITRATE(75.5));
+
+ //nbBytes = opus_encode(encoder, in, FRAME_SIZE, cbits, MAX_PACKET_SIZE);
+
+ int e;
+ opusSFX = op_open_file("AUDIO/SFX.opus", &e);
+
return true;
}