Просмотр исходного кода

FMOD Audio listener implemented

BearishSun 9 лет назад
Родитель
Сommit
4bc7f3cc10

+ 28 - 1
Source/BansheeFMOD/Include/BsFMODAudio.h

@@ -44,7 +44,28 @@ namespace BansheeEngine
 		AudioDevice getDefaultDevice() const override { return mDefaultDevice; }
 
 		/** @copydoc Audio::getAllDevices */
-		const Vector<AudioDevice>& getAllDevices() const override { return mAllDevices; };
+		const Vector<AudioDevice>& getAllDevices() const override { return mAllDevices; }
+
+		/** @name Internal 
+		 *  @{
+		 */
+
+		/** Registers a new AudioListener. Should be called on listener creation. */
+		void _registerListener(FMODAudioListener* listener);
+
+		/** Unregisters an existing AudioListener. Should be called before listener destruction. */
+		void _unregisterListener(FMODAudioListener* listener);
+
+		/** Registers a new AudioSource. Should be called on source creation. */
+		void _registerSource(FMODAudioSource* source);
+
+		/** Unregisters an existing AudioSource. Should be called before source destruction. */
+		void _unregisterSource(FMODAudioSource* source);
+
+		/** Returns internal FMOD system instance. */
+		FMOD::System* _getFMOD() const { return mFMOD; }
+
+		/** @} */
 	private:
 		/** @copydoc Audio::createClip */
 		SPtr<AudioClip> createClip(const SPtr<DataStream>& samples, UINT32 streamSize, UINT32 numSamples,
@@ -56,12 +77,18 @@ namespace BansheeEngine
 		/** @copydoc Audio::createSource */
 		SPtr<AudioSource> createSource() override;
 
+		/** Rebuilds information about all listeners. Should be called when listener list changes. */
+		void rebuildListeners();
+
 		FMOD::System* mFMOD;
 		FMOD::ChannelGroup* mMasterChannelGroup;
 
 		float mVolume;
 		bool mIsPaused;
 
+		Vector<FMODAudioListener*> mListeners;
+		UnorderedSet<FMODAudioSource*> mSources;
+
 		Vector<AudioDevice> mAllDevices;
 		AudioDevice mDefaultDevice;
 		AudioDevice mActiveDevice;

+ 8 - 0
Source/BansheeFMOD/Include/BsFMODAudioListener.h

@@ -29,6 +29,14 @@ namespace BansheeEngine
 
 		/** @copydoc AudioListener::setVelocity */
 		void setVelocity(const Vector3& velocity) override;
+
+	private:
+		friend class FMODAudio;
+
+		/** Called by the FMODAudio system when the listener list changes. */
+		void rebuild(INT32 id);
+
+		INT32 mId;
 	};
 
 	/** @} */

+ 4 - 0
Source/BansheeFMOD/Include/BsFMODPrerequisites.h

@@ -22,6 +22,10 @@
 
 namespace BansheeEngine
 {
+	class FMODAudioListener;
+	class FMODAudioSource;
+	class FMODAudioClip;
+
 	/** Contains data describing an audio file. */
 	struct AudioFileInfo
 	{

+ 47 - 0
Source/BansheeFMOD/Source/BsFMODAudio.cpp

@@ -79,6 +79,7 @@ namespace BansheeEngine
 
 	FMODAudio::~FMODAudio()
 	{
+		assert(mListeners.size() == 0 && mSources.size() == 0); // Everything should be destroyed at this point
 		mFMOD->release();
 	}
 
@@ -140,6 +141,52 @@ namespace BansheeEngine
 		return bs_shared_ptr_new<FMODAudioSource>();
 	}
 
+	void FMODAudio::_registerListener(FMODAudioListener* listener)
+	{
+		mListeners.push_back(listener);
+
+		rebuildListeners();
+	}
+
+	void FMODAudio::_unregisterListener(FMODAudioListener* listener)
+	{
+		auto iterFind = std::find(mListeners.begin(), mListeners.end(), listener);
+		if (iterFind != mListeners.end())
+			mListeners.erase(iterFind);
+
+		rebuildListeners();
+	}
+
+	void FMODAudio::rebuildListeners()
+	{
+		INT32 numListeners = (INT32)mListeners.size();
+		if (numListeners > 0)
+		{
+			mFMOD->set3DNumListeners(numListeners);
+			for (INT32 i = 0; i < numListeners; i++)
+				mListeners[i]->rebuild(i);
+		}
+		else // Always keep at least one listener
+		{
+			mFMOD->set3DNumListeners(1);
+			FMOD_VECTOR zero = { 0.0f, 0.0f, 0.0f };
+			FMOD_VECTOR forward = { 0.0f, 0.0f, -1.0f };
+			FMOD_VECTOR up = { 0.0f, 1.0f, 0.0f };
+
+			mFMOD->set3DListenerAttributes(0, &zero, &zero, &forward, &up);
+		}
+	}
+
+	void FMODAudio::_registerSource(FMODAudioSource* source)
+	{
+		mSources.insert(source);
+	}
+
+	void FMODAudio::_unregisterSource(FMODAudioSource* source)
+	{
+		mSources.erase(source);
+	}
+
 	FMODAudio& gFMODAudio()
 	{
 		return static_cast<FMODAudio&>(FMODAudio::instance());

+ 31 - 6
Source/BansheeFMOD/Source/BsFMODAudioListener.cpp

@@ -7,39 +7,64 @@ namespace BansheeEngine
 {
 	FMODAudioListener::FMODAudioListener()
 	{
-		// TODO
+		gFMODAudio()._registerListener(this);
 	}
 
 	FMODAudioListener::~FMODAudioListener()
 	{
-		// TODO
+		gFMODAudio()._unregisterListener(this);
 	}
 
 	void FMODAudioListener::setPosition(const Vector3& position)
 	{
 		AudioListener::setPosition(position);
 
-		// TODO
+		FMOD::System* fmod = gFMODAudio()._getFMOD();
+		FMOD_VECTOR value = { position.x, position.y, position.z };
+
+		fmod->set3DListenerAttributes(mId, &value, nullptr, nullptr, nullptr);
 	}
 
 	void FMODAudioListener::setDirection(const Vector3& direction)
 	{
 		AudioListener::setDirection(direction);
 
-		// TODO
+		FMOD::System* fmod = gFMODAudio()._getFMOD();
+		FMOD_VECTOR value = { direction.x, direction.y, direction.z };
+
+		fmod->set3DListenerAttributes(mId, nullptr, nullptr, &value, nullptr);
 	}
 
 	void FMODAudioListener::setUp(const Vector3& up)
 	{
 		AudioListener::setUp(up);
 
-		// TODO
+		FMOD::System* fmod = gFMODAudio()._getFMOD();
+		FMOD_VECTOR value = { up.x, up.y, up.z };
+
+		fmod->set3DListenerAttributes(mId, nullptr, nullptr, nullptr, &value);
 	}
 
 	void FMODAudioListener::setVelocity(const Vector3& velocity)
 	{
 		AudioListener::setVelocity(velocity);
 
-		// TODO
+		FMOD::System* fmod = gFMODAudio()._getFMOD();
+		FMOD_VECTOR value = { velocity.x, velocity.y, velocity.z };
+
+		fmod->set3DListenerAttributes(mId, nullptr, &value, nullptr, nullptr);
+	}
+
+	void FMODAudioListener::rebuild(INT32 id)
+	{
+		mId = id;
+
+		FMOD::System* fmod = gFMODAudio()._getFMOD();
+		FMOD_VECTOR position = { mPosition.x, mPosition.y, mPosition.z };
+		FMOD_VECTOR velocity = { mVelocity.x, mVelocity.y, mVelocity.z };
+		FMOD_VECTOR forward = { mDirection.x, mDirection.y, mDirection.z };
+		FMOD_VECTOR up = { mUp.x, mUp.y, mUp.z };
+
+		fmod->set3DListenerAttributes(mId, &position, &velocity, &forward, &up);
 	}
 }

+ 2 - 0
Source/BansheeFMOD/Source/BsFMODAudioSource.cpp

@@ -8,11 +8,13 @@ namespace BansheeEngine
 {
 	FMODAudioSource::FMODAudioSource()
 	{
+		gFMODAudio()._registerSource(this);
 		// TODO
 	}
 
 	FMODAudioSource::~FMODAudioSource()
 	{
+		gFMODAudio()._unregisterSource(this);
 		// TODO
 	}