From fd6b4beeb7c6d966b9b04dc67d78407511a52ef1 Mon Sep 17 00:00:00 2001 From: Byurrer <byurrer@mail.ru> Date: Sun, 14 Jun 2020 21:54:22 +0300 Subject: [PATCH] Added 3D sound --- proj/xSound/vs2013/xSound.vcxproj | 10 ++-- sdks/mital | 2 +- source/common | 2 +- source/xEngine/Engine.cpp | 9 ++-- source/xSound/SoundBase.h | 2 +- source/xSound/SoundEmitter.cpp | 44 ++++++++++++---- source/xSound/SoundEmitter.h | 5 +- source/xSound/SoundLayer.cpp | 18 +++++-- source/xSound/SoundLayer.h | 4 +- source/xSound/SoundPlayer.cpp | 14 ++++- source/xSound/SoundPlayer.h | 5 +- source/xSound/SoundSystem.cpp | 6 ++- source/xSound/SoundSystem.h | 23 ++++++++- source/xSound/plugin_main.cpp | 86 ++++++++++++++++++++++++++++--- 14 files changed, 188 insertions(+), 42 deletions(-) diff --git a/proj/xSound/vs2013/xSound.vcxproj b/proj/xSound/vs2013/xSound.vcxproj index 656c8e772..fc868bf74 100644 --- a/proj/xSound/vs2013/xSound.vcxproj +++ b/proj/xSound/vs2013/xSound.vcxproj @@ -71,24 +71,24 @@ <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);../../../source;../../../sdks/mital/source/;</IncludePath> <OutDir>../../../build/bin/plugins/</OutDir> <TargetName>$(ProjectName)_d</TargetName> - <LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);../../../sdks/mital/lib/;</LibraryPath> + <LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);../../../libs;../../../sdks/mital/lib/;</LibraryPath> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <TargetName>$(ProjectName)_d</TargetName> - <LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);../../../sdks/mital/lib64/;</LibraryPath> + <LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);../../../libs64;../../../sdks/mital/lib64/;</LibraryPath> <LinkIncremental>false</LinkIncremental> - <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);../../../source;../../../sdks/mital/source/;</IncludePath> + <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);../../../source;../../../sdks/mital/source/;../../../sdks/;</IncludePath> <OutDir>../../../build/bin64/plugins/</OutDir> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <LinkIncremental>false</LinkIncremental> <OutDir>../../../build/bin/plugins/</OutDir> <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);../../../source;../../../sdks/mital/source/;</IncludePath> - <LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);../../../sdks/mital/lib/;</LibraryPath> + <LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);../../../libs;../../../sdks/mital/lib/;</LibraryPath> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);../../../source;../../../sdks/mital/source/;</IncludePath> - <LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);../../../sdks/mital/lib64/;</LibraryPath> + <LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);../../../libs64;../../../sdks/mital/lib64/;</LibraryPath> <LinkIncremental>false</LinkIncremental> <OutDir>../../../build/bin64/plugins/</OutDir> </PropertyGroup> diff --git a/sdks/mital b/sdks/mital index e3bf76315..480bfc6f6 160000 --- a/sdks/mital +++ b/sdks/mital @@ -1 +1 @@ -Subproject commit e3bf76315c38eba4fde0e1b64f7afbcadeffddb3 +Subproject commit 480bfc6f618baa95129fcff28503727b43ea5940 diff --git a/source/common b/source/common index 0dc806046..e41e5d467 160000 --- a/source/common +++ b/source/common @@ -1 +1 @@ -Subproject commit 0dc80604688a34568513f10d19139692174fc0c9 +Subproject commit e41e5d467c8436fb9fed92c66eebfb3a590e3e98 diff --git a/source/xEngine/Engine.cpp b/source/xEngine/Engine.cpp index 427f0d820..3ab5605f4 100644 --- a/source/xEngine/Engine.cpp +++ b/source/xEngine/Engine.cpp @@ -174,10 +174,11 @@ bool XMETHODCALLTYPE CEngine::initGraphics(XWINDOW_OS_HANDLE hWindow, IXEngineCa IXSoundSystem *pSound = (IXSoundSystem*)(m_pCore->getPluginManager()->getInterface(IXSOUNDSYSTEM_GUID)); IXSoundLayer *pMasterLayer = pSound->createMasterLayer(&oAudioDesc, "master"); pMasterLayer->play(true); - /*IXSoundPlayer *pPlayer = pMasterLayer->newSoundPlayer("sounds/guitar_10.ogg", SOUND_DTYPE_2D); - //pPlayer->setLoop(SOUND_LOOP_SIMPLE); - pPlayer->play(); - IXSoundEmitter *pEmitter = pMasterLayer->newSoundEmitter("sounds/ak74_shoot.ogg", SOUND_DTYPE_2D); + /*IXSoundPlayer *pPlayer = pMasterLayer->newSoundPlayer("sounds/guitar_10.ogg", SOUND_DTYPE_3D); + pPlayer->setWorldPos(float3(-11.084, 0.435, -18.707)); + pPlayer->setLoop(SOUND_LOOP_SIMPLE); + pPlayer->play();*/ + /*IXSoundEmitter *pEmitter = pMasterLayer->newSoundEmitter("sounds/ak74_shoot.ogg", SOUND_DTYPE_2D); //pEmitter->play(); IXSoundEmitter *pEmitter2 = pMasterLayer->newSoundEmitter("sounds/ak74_shoot.ogg", SOUND_DTYPE_2D); diff --git a/source/xSound/SoundBase.h b/source/xSound/SoundBase.h index 6721f5e86..b6de20455 100644 --- a/source/xSound/SoundBase.h +++ b/source/xSound/SoundBase.h @@ -54,7 +54,7 @@ protected: //IAudioBuffer *m_pAB = NULL; //! дистанция слышимости - float m_fDist = 0.f; + float m_fDist = 10.f; //! мировая позиция звука float3 m_vWorldPos; diff --git a/source/xSound/SoundEmitter.cpp b/source/xSound/SoundEmitter.cpp index d127bfe00..153610790 100644 --- a/source/xSound/SoundEmitter.cpp +++ b/source/xSound/SoundEmitter.cpp @@ -36,22 +36,31 @@ void XMETHODCALLTYPE CSoundEmitter::play() if (!m_pLayer->isPlaying()) return; + float3 vPos, vLook, vUp; + m_pLayer->getObserverParam(&vPos, &vLook, &vUp); + + IAudioBuffer *pAB = NULL; + //проход по массиву инстансов звука, если есть первый попавшийся не проигрываемые тогда его проигрываем for (int i = 0, il = m_aInstances.size(); i<il; ++i) { if (!(m_aInstances[i].pAB->isPlaying())) { - m_aInstances[i].pAB->setVolume(m_fVolume); - m_aInstances[i].pAB->play(true); - return; + pAB = m_aInstances[i].pAB; + continue; } } - //если пришли сюда, значит нет свободных инстансов, создаем новый и проигрыаем - IAudioBuffer *pInst = m_aInstances[0].pAB->newInstance(); - pInst->setVolume(m_fVolume); - pInst->play(true); - m_aInstances.push_back(pInst); + if (!pAB) + { + //если пришли сюда, значит нет свободных инстансов, создаем новый и проигрыаем + IAudioBuffer *pInst = m_aInstances[0].pAB->newInstance(); + pAB = pInst; + m_aInstances.push_back(pInst); + } + + Com3D(pAB, m_fDist, m_vWorldPos, vPos, vLook, vUp); + pAB->play(true); } //************************************************************************** @@ -78,11 +87,12 @@ void CSoundEmitter::pause() //************************************************************************** -bool CSoundEmitter::create(CSoundLayer *pLayer, IXAudioCodecTarget *pCodecTarget) +bool CSoundEmitter::create(CSoundLayer *pLayer, IXAudioCodecTarget *pCodecTarget, SOUND_DTYPE dtype) { if (!pCodecTarget || !pLayer) return false; + m_dtype = dtype; AudioRawDesc oDesc; pCodecTarget->getDesc(&oDesc); m_pLayer = pLayer; @@ -105,3 +115,19 @@ bool CSoundEmitter::create(CSoundLayer *pLayer, IXAudioCodecTarget *pCodecTarget return true; } + +//########################################################################## + +void CSoundEmitter::update(const float3 &vListenerPos, const float3 &vListenerDir, const float3 &vListenerUp) +{ + if (m_dtype == SOUND_DTYPE_2D) + return; + + for (int i = 0, il = m_aInstances.size(); i < il; ++i) + { + if (m_aInstances[i].pAB->isPlaying()) + { + Com3D(m_aInstances[i].pAB, m_fDist, m_vWorldPos, vListenerPos, vListenerDir, vListenerUp); + } + } +} \ No newline at end of file diff --git a/source/xSound/SoundEmitter.h b/source/xSound/SoundEmitter.h index 87a1302fb..318fe7885 100644 --- a/source/xSound/SoundEmitter.h +++ b/source/xSound/SoundEmitter.h @@ -12,6 +12,7 @@ See the license in LICENSE #include <mital.h> #include "SoundTypes.h" +#include "SoundSystem.h" //########################################################################## @@ -31,13 +32,13 @@ public: //! остановка проигрывания void pause(); - //void update(); + void update(const float3 &vListenerPos, const float3 &vListenerDir, const float3 &vListenerUp); protected: friend CSoundLayer; - bool create(CSoundLayer *pLayer, IXAudioCodecTarget *pCodecTarget); + bool create(CSoundLayer *pLayer, IXAudioCodecTarget *pCodecTarget, SOUND_DTYPE dtype); struct Instance { diff --git a/source/xSound/SoundLayer.cpp b/source/xSound/SoundLayer.cpp index aa9a298a9..618aa56a9 100644 --- a/source/xSound/SoundLayer.cpp +++ b/source/xSound/SoundLayer.cpp @@ -209,7 +209,7 @@ IXSoundEmitter* XMETHODCALLTYPE CSoundLayer::newSoundEmitter(const char *szName, return NULL; pEmitter = new CSoundEmitter(); - pEmitter->create(this, pCodecTarget); + pEmitter->create(this, pCodecTarget, dtype); } addSndEmitter(pEmitter, szName); @@ -236,7 +236,7 @@ IXSoundPlayer* XMETHODCALLTYPE CSoundLayer::newSoundPlayer(const char *szName, S return NULL; pPlayer = new CSoundPlayer(); - pPlayer->create(this, pCodecTarget); + pPlayer->create(this, pCodecTarget, dtype); } addSndPlayer(pPlayer, szName); @@ -280,13 +280,21 @@ bool XMETHODCALLTYPE CSoundLayer::isPlaying() const return m_isPlaying; } -void CSoundLayer::update() +void CSoundLayer::update(const float3 &vListenerPos, const float3 &vListenerDir, const float3 &vListenerUp) { for (maplayer::Iterator i = m_mapLayers.begin(); i; i++) - m_mapLayers[i.first]->update(); + m_mapLayers[i.first]->update(vListenerPos, vListenerDir, vListenerUp); for (mapsoundplayer::Iterator i = m_mapSndPlayers.begin(); i; i++) - m_mapSndPlayers[i.first]->update(); + m_mapSndPlayers[i.first]->update(vListenerPos, vListenerDir, vListenerUp); + + for (mapsoundemitter::Iterator i = m_mapSndEmitters.begin(); i; i++) + m_mapSndEmitters[i.first]->update(vListenerPos, vListenerDir, vListenerUp); +} + +void CSoundLayer::getObserverParam(float3 *pPos, float3 *pLook, float3 *pUp) +{ + m_pSoundSystem->getObserverParam(pPos, pLook, pUp); } bool CSoundLayer::matchPrimaryLayer(const AudioRawDesc *pDesc) diff --git a/source/xSound/SoundLayer.h b/source/xSound/SoundLayer.h index a95a93356..06b901608 100644 --- a/source/xSound/SoundLayer.h +++ b/source/xSound/SoundLayer.h @@ -37,7 +37,9 @@ public: uint32_t getStreamChunkSize(AudioRawDesc *pDesc) const; IAudioBuffer* createAudioBuffer(AB_TYPE type, const AudioRawDesc *pDesc); - void update(); + void update(const float3 &vListenerPos, const float3 &vListenerDir, const float3 &vListenerUp); + + void getObserverParam(float3 *pPos, float3 *pLook, float3 *pUp); protected: diff --git a/source/xSound/SoundPlayer.cpp b/source/xSound/SoundPlayer.cpp index 3220693dd..648532c1f 100644 --- a/source/xSound/SoundPlayer.cpp +++ b/source/xSound/SoundPlayer.cpp @@ -39,11 +39,12 @@ CSoundPlayer* CSoundPlayer::newInstance() //************************************************************************** -bool CSoundPlayer::create(CSoundLayer *pLayer, IXAudioCodecTarget *pCodecTarget) +bool CSoundPlayer::create(CSoundLayer *pLayer, IXAudioCodecTarget *pCodecTarget, SOUND_DTYPE dtype) { if (!pCodecTarget || !pLayer) return false; + m_dtype = dtype; m_pLayer = pLayer; m_pCodecTarget = pCodecTarget; AudioRawDesc oDesc; @@ -95,6 +96,10 @@ void XMETHODCALLTYPE CSoundPlayer::play() if (!m_pLayer->isPlaying()) return; + float3 vPos, vLook, vUp; + m_pLayer->getObserverParam(&vPos, &vLook, &vUp); + + Com3D(m_pAB, m_fDist, m_vWorldPos, vPos, vLook, vUp); m_pAB->play(true); m_state = SOUND_STATE_PLAY; } @@ -243,11 +248,16 @@ uint32_t CSoundPlayer::getPosBytes() const //########################################################################## -void CSoundPlayer::update() +void CSoundPlayer::update(const float3 &vListenerPos, const float3 &vListenerDir, const float3 &vListenerUp) { if (!m_pLayer->isPlaying()) return; + if (m_dtype == SOUND_DTYPE_3D) + { + Com3D(m_pAB, m_fDist, m_vWorldPos, vListenerPos, vListenerDir, vListenerUp); + } + if (!m_pStream) return; diff --git a/source/xSound/SoundPlayer.h b/source/xSound/SoundPlayer.h index 24c157b1a..e21098dd4 100644 --- a/source/xSound/SoundPlayer.h +++ b/source/xSound/SoundPlayer.h @@ -12,6 +12,7 @@ See the license in LICENSE #include <mital.h> #include "SoundTypes.h" +#include "SoundSystem.h" //########################################################################## @@ -43,9 +44,9 @@ protected: friend CSoundLayer; - void update(); + void update(const float3 &vListenerPos, const float3 &vListenerDir, const float3 &vListenerUp); - bool create(CSoundLayer *pLayer, IXAudioCodecTarget *pCodecTarget); + bool create(CSoundLayer *pLayer, IXAudioCodecTarget *pCodecTarget, SOUND_DTYPE dtype); //! возвращает текущую позицию проигрывания звука в байтах uint32_t getPosBytes() const; diff --git a/source/xSound/SoundSystem.cpp b/source/xSound/SoundSystem.cpp index 46fb577ca..7109a7ce1 100644 --- a/source/xSound/SoundSystem.cpp +++ b/source/xSound/SoundSystem.cpp @@ -49,8 +49,12 @@ CSoundSystem::~CSoundSystem() void XMETHODCALLTYPE CSoundSystem::update(const float3 &vListenerPos, const float3 &vListenerDir, const float3 &vListenerUp) { + std::lock_guard<std::mutex> guard(m_oMutexUpdate); + if(m_pMasterLayer) - m_pMasterLayer->update(); + m_pMasterLayer->update(vListenerPos, vListenerDir, vListenerUp); + + m_vObserverPos = vListenerPos; m_vObserverLook = vListenerDir; m_vObserverUp = vListenerUp; } //************************************************************************** diff --git a/source/xSound/SoundSystem.h b/source/xSound/SoundSystem.h index 4bfd0841b..62ffad2c7 100644 --- a/source/xSound/SoundSystem.h +++ b/source/xSound/SoundSystem.h @@ -21,7 +21,7 @@ See the license in LICENSE //########################################################################## -inline float Com3DPan(float3 &vSnd, float3 &vListenerPos, float3 &vListenerDir, float3 &vListenerUp) +inline float Com3DPan(const float3 &vSnd, const float3 &vListenerPos, const float3 &vListenerDir, const float3 &vListenerUp) { float3 side = SMVector3Cross(vListenerUp, vListenerDir); SMVector3Normalize(side); @@ -32,11 +32,21 @@ inline float Com3DPan(float3 &vSnd, float3 &vListenerPos, float3 &vListenerDir, return pan; } +inline void Com3D(IAudioBuffer *pAB, float fDist, const float3 &vSnd, const float3 &vListenerPos, const float3 &vListenerDir, const float3 &vListenerUp) +{ + float fPan = Com3DPan(vSnd, vListenerPos, vListenerDir, vListenerUp); + float fVolume = 1.f - saturatef(SMVector3Distance(vSnd, vListenerPos) / fDist); + fPan = lerpf(fPan, 0.f, fVolume); + pAB->setPan(fPan); + pAB->setVolume(fVolume); +} + //########################################################################## class CSoundSystem: public IXUnknownImplementation<IXSoundSystem> { public: + SX_ALIGNED_OP_MEM CSoundSystem(IXCore *pXCore); ~CSoundSystem(); @@ -50,6 +60,14 @@ public: IXCore* getCore() const; + void getObserverParam(float3 *pPos, float3 *pLook, float3 *pUp) + { + while (!m_oMutexUpdate.try_lock()){} + m_oMutexUpdate.unlock(); + + *pPos = m_vObserverPos; *pLook = m_vObserverLook; *pUp = m_vObserverUp; + } + protected: friend CSoundLayer; @@ -69,6 +87,9 @@ protected: typedef AssotiativeArray<String, IXAudioCodec*> mapcodec; mapcodec m_mapCodecs; + + float3 m_vObserverPos, m_vObserverLook, m_vObserverUp; + std::mutex m_oMutexUpdate; }; #endif diff --git a/source/xSound/plugin_main.cpp b/source/xSound/plugin_main.cpp index a23d35dcb..f21f993d4 100644 --- a/source/xSound/plugin_main.cpp +++ b/source/xSound/plugin_main.cpp @@ -3,6 +3,7 @@ #include <xcommon/IXUpdatable.h> #include "SoundSystem.h" #include <Audio.h> +#include <gcore/sxgcore.h> #if defined(_DEBUG) #pragma comment(lib, "mital_d.lib") @@ -10,13 +11,55 @@ #pragma comment(lib, "mital.lib") #endif +//########################################################################## -class CUpdatable : public IXUnknownImplementation<IXUpdatable> +class CObserverChangedEventListener : public IEventListener<XEventObserverChanged> { public: - CUpdatable(CSoundSystem *pSoundSystem) + SX_ALIGNED_OP_MEM + + CObserverChangedEventListener(IXCore *pCore) + { + m_pObserverChangedEventChannel = pCore->getEventChannel<XEventObserverChanged>(EVENT_OBSERVER_CHANGED_GUID); + m_pObserverChangedEventChannel->addListener(this); + } + + ~CObserverChangedEventListener() + { + m_pObserverChangedEventChannel->removeListener(this); + } + + void onEvent(const XEventObserverChanged *pData) override + { + std::lock_guard<std::mutex> guard(m_oMutex); + pData->pCamera->getPosition(&m_vPos); + pData->pCamera->getUp(&m_vUp); + pData->pCamera->getLook(&m_vLook); + } + + void getObserverParam(float3 *pPos, float3 *pLook, float3 *pUp) + { + std::lock_guard<std::mutex> guard(m_oMutex); + *pPos = m_vPos; *pLook = m_vLook; *pUp = m_vUp; + } + +protected: + IEventChannel<XEventObserverChanged> *m_pObserverChangedEventChannel = NULL; + float3 m_vPos, m_vLook, m_vUp; + std::mutex m_oMutex; +}; + +//########################################################################## + +class CUpdatableSoundSystem : public IXUnknownImplementation<IXUpdatable> +{ +public: + SX_ALIGNED_OP_MEM + + CUpdatableSoundSystem(CSoundSystem *pSoundSystem, CObserverChangedEventListener *pObserverListener) { m_pSoundSystem = pSoundSystem; + m_pObserverListener = pObserverListener; } UINT startup() override @@ -30,9 +73,33 @@ public: ID run(float fDelta) override { - float3 v; + float3 vPos, vLook, vUp; + + if (m_pObserverListener) + m_pObserverListener->getObserverParam(&vPos, &vLook, &vUp); + if (m_pSoundSystem) - m_pSoundSystem->update(v, v, v); + m_pSoundSystem->update(vPos, vLook, vUp); + + /*if (!m_pEmitter) + { + IXSoundLayer *pMasterLayer = m_pSoundSystem->findLayer("master"); + if (pMasterLayer) + { + m_pEmitter = pMasterLayer->newSoundEmitter("sounds/ak74_shoot.ogg", SOUND_DTYPE_3D); + m_pEmitter->setWorldPos(float3(-11.084, 0.435, -18.707)); + m_pEmitter->setDistance(50); + //pEmitter->play(); + } + } + else + { + if (GetAsyncKeyState('I')) + { + m_pEmitter->play(); + //Sleep(100); + } + }*/ return -1; } @@ -44,8 +111,11 @@ public: protected: CSoundSystem *m_pSoundSystem = NULL; + CObserverChangedEventListener *m_pObserverListener = NULL; + IXSoundEmitter *m_pEmitter = NULL; }; +//########################################################################## class CSoundSystemPlugin : public IXUnknownImplementation<IXPlugin> { @@ -55,7 +125,8 @@ public: { m_pCore = pCore; m_pSoundSystem = new CSoundSystem(m_pCore); - m_pUpdatable = new CUpdatable(m_pSoundSystem); + m_pObserverListener = new CObserverChangedEventListener(m_pCore); + m_pUpdatableSoundSystem = new CUpdatableSoundSystem(m_pSoundSystem, m_pObserverListener); } void XMETHODCALLTYPE shutdown() override @@ -87,7 +158,7 @@ public: if (guid == IXSOUNDSYSTEM_GUID) return m_pSoundSystem; else if (guid == IXUPDATABLE_GUID) - return m_pUpdatable; + return m_pUpdatableSoundSystem; return(NULL); } @@ -95,7 +166,8 @@ public: protected: IXCore *m_pCore; CSoundSystem *m_pSoundSystem = NULL; - CUpdatable *m_pUpdatable = NULL; + CUpdatableSoundSystem *m_pUpdatableSoundSystem = NULL; + CObserverChangedEventListener *m_pObserverListener = NULL; }; DECLARE_XPLUGIN(CSoundSystemPlugin); -- GitLab