فهرست منبع

FMOD Startup/Shutdown/Update and device enumeration
Fixed optimized debug linker flags for MSVC

BearishSun 9 سال پیش
والد
کامیت
ed3b7db038
3فایلهای تغییر یافته به همراه92 افزوده شده و 15 حذف شده
  1. 4 0
      Source/BansheeFMOD/Include/BsFMODAudio.h
  2. 87 14
      Source/BansheeFMOD/Source/BsFMODAudio.cpp
  3. 1 1
      Source/CMakeLists.txt

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

@@ -4,6 +4,7 @@
 
 
 #include "BsFMODPrerequisites.h"
 #include "BsFMODPrerequisites.h"
 #include "BsAudio.h"
 #include "BsAudio.h"
+#include "fmod.hpp"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -55,6 +56,9 @@ namespace BansheeEngine
 		/** @copydoc Audio::createSource */
 		/** @copydoc Audio::createSource */
 		SPtr<AudioSource> createSource() override;
 		SPtr<AudioSource> createSource() override;
 
 
+		FMOD::System* mFMOD;
+		FMOD::ChannelGroup* mMasterChannelGroup;
+
 		float mVolume;
 		float mVolume;
 		bool mIsPaused;
 		bool mIsPaused;
 
 

+ 87 - 14
Source/BansheeFMOD/Source/BsFMODAudio.cpp

@@ -1,26 +1,91 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "BsFMODAudio.h"
 #include "BsFMODAudio.h"
+#include "BsFMODAudioClip.h"
+#include "BsFMODAudioSource.h"
+#include "BsFMODAudioListener.h"
 #include "BsMath.h"
 #include "BsMath.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
+	void* F_CALLBACK FMODAlloc(unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr)
+	{
+		return bs_alloc(size);
+	}
+
+	void* F_CALLBACK FMODRealloc(void *ptr, unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr)
+	{
+		// Note: Not using Banshee's allocators, but have no easy alternative to implement realloc manually.
+		// This is okay to use in combination with general purpose bs_alloc/bs_free since they internally use malloc/free.
+		return realloc(ptr, size);
+	}
+
+	void F_CALLBACK FMODFree(void *ptr, FMOD_MEMORY_TYPE type, const char *sourcestr)
+	{
+		bs_free(ptr);
+	}
+
+	float F_CALLBACK FMOD3DRolloff(FMOD_CHANNELCONTROL* channelControl, float distance)
+	{
+		FMODAudioSource* source = nullptr;
+		FMOD::Channel* channel = (FMOD::Channel*)channelControl;
+		channel->getUserData((void**)&source);
+
+		// Calculate standard inverse rolloff, but use different attenuation per source (also ignore max distance)
+		float minDistance = source->getMinDistance();
+		float attenuation = source->getAttenuation();
+		
+		distance = std::max(distance, minDistance);
+		return minDistance / (minDistance + attenuation * (distance - minDistance));
+	}
+
 	FMODAudio::FMODAudio()
 	FMODAudio::FMODAudio()
-		:mVolume(1.0f), mIsPaused(false)
+		:mFMOD(nullptr), mMasterChannelGroup(nullptr), mVolume(1.0f), mIsPaused(false)
 	{
 	{
-		// TODO - Enumerate devices, init FMOD
+		FMOD::Memory_Initialize(nullptr, 0, &FMODAlloc, &FMODRealloc, &FMODFree);
+		FMOD::System_Create(&mFMOD);
+
+		FMOD_ADVANCEDSETTINGS advancedSettings;
+		memset(&advancedSettings, 0, sizeof(advancedSettings));
+		advancedSettings.cbSize = sizeof(advancedSettings);
+		advancedSettings.vol0virtualvol = 0.001f;
+
+		mFMOD->setAdvancedSettings(&advancedSettings);
+		mFMOD->init(512, FMOD_INIT_3D_RIGHTHANDED | FMOD_INIT_THREAD_UNSAFE | FMOD_INIT_VOL0_BECOMES_VIRTUAL, nullptr);
+		mFMOD->setStreamBufferSize(65536, FMOD_TIMEUNIT_RAWBYTES);
+		mFMOD->set3DRolloffCallback(&FMOD3DRolloff);
+
+		mFMOD->getMasterChannelGroup(&mMasterChannelGroup);
+
+		INT32 numDevices;
+		mFMOD->getNumDrivers(&numDevices);
+
+		mAllDevices.resize(numDevices);
+		char nameBuffer[256];
+		for(INT32 i = 0; i < numDevices; i++)
+		{
+			mFMOD->getDriverInfo(i, nameBuffer, sizeof(nameBuffer), nullptr, nullptr, nullptr, nullptr);
+			mAllDevices[i].name = toWString(nameBuffer);
+		}
+
+		INT32 defaultDevice = 0;
+		mFMOD->getDriver(&defaultDevice);
+		if(defaultDevice < numDevices)
+		{
+			mDefaultDevice.name = mAllDevices[defaultDevice].name;
+			mActiveDevice.name = mAllDevices[defaultDevice].name;
+		}
 	}
 	}
 
 
 	FMODAudio::~FMODAudio()
 	FMODAudio::~FMODAudio()
 	{
 	{
-		// TODO - Shutdown FMOD
+		mFMOD->release();
 	}
 	}
 
 
 	void FMODAudio::setVolume(float volume)
 	void FMODAudio::setVolume(float volume)
 	{
 	{
 		mVolume = Math::clamp01(volume);
 		mVolume = Math::clamp01(volume);
-
-		// TODO
+		mMasterChannelGroup->setVolume(mVolume);
 	}
 	}
 
 
 	float FMODAudio::getVolume() const
 	float FMODAudio::getVolume() const
@@ -35,36 +100,44 @@ namespace BansheeEngine
 
 
 		mIsPaused = paused;
 		mIsPaused = paused;
 
 
-		// TODO
+		// TODO - Iterate over all sound sources, pause them
 	}
 	}
 
 
 	void FMODAudio::_update()
 	void FMODAudio::_update()
 	{
 	{
-		// TODO - Call FMOD update, update streaming?
+		mFMOD->update();
+
+		// TODO - Update streaming?
 	}
 	}
 
 
 	void FMODAudio::setActiveDevice(const AudioDevice& device)
 	void FMODAudio::setActiveDevice(const AudioDevice& device)
 	{
 	{
-		// TODO
+		for(UINT32 i = 0; i < (UINT32)mAllDevices.size(); i++)
+		{
+			if(device.name == mAllDevices[i].name)
+			{
+				mFMOD->setDriver(i);
+				return;
+			}
+		}
+
+		LOGWRN("Failed changing audio device to: " + toString(device.name));
 	}
 	}
 
 
 	SPtr<AudioClip> FMODAudio::createClip(const SPtr<DataStream>& samples, UINT32 streamSize, UINT32 numSamples,
 	SPtr<AudioClip> FMODAudio::createClip(const SPtr<DataStream>& samples, UINT32 streamSize, UINT32 numSamples,
 		const AUDIO_CLIP_DESC& desc)
 		const AUDIO_CLIP_DESC& desc)
 	{
 	{
-		// TODO
-		return nullptr;
+		return bs_core_ptr_new<FMODAudioClip>(samples, streamSize, numSamples, desc);
 	}
 	}
 
 
 	SPtr<AudioListener> FMODAudio::createListener()
 	SPtr<AudioListener> FMODAudio::createListener()
 	{
 	{
-		// TODO
-		return nullptr;
+		return bs_shared_ptr_new<FMODAudioListener>();
 	}
 	}
 
 
 	SPtr<AudioSource> FMODAudio::createSource()
 	SPtr<AudioSource> FMODAudio::createSource()
 	{
 	{
-		// TODO
-		return nullptr;
+		return bs_shared_ptr_new<FMODAudioSource>();
 	}
 	}
 
 
 	FMODAudio& gFMODAudio()
 	FMODAudio& gFMODAudio()

+ 1 - 1
Source/CMakeLists.txt

@@ -64,7 +64,7 @@ if(MSVC)
 	set(BS_LINKER_FLAGS_RELEASE "${BS_LINKER_FLAGS_COMMON} /LTCG /INCREMENTAL:NO /OPT:REF")
 	set(BS_LINKER_FLAGS_RELEASE "${BS_LINKER_FLAGS_COMMON} /LTCG /INCREMENTAL:NO /OPT:REF")
 	
 	
 	if(BS_64BIT)
 	if(BS_64BIT)
-		set(BS_LINKER_FLAGS_OPTIMIZEDDEBUG "${BS_LINKER_FLAGS_OPTIMIZEDDEBUG} /OPT:ICF")
+		set(BS_LINKER_FLAGS_OPTIMIZEDDEBUG "${BS_LINKER_FLAGS_OPTIMIZEDDEBUG} /OPT:ICF /INCREMENTAL:NO")
 		set(BS_LINKER_FLAGS_RELEASE "${BS_LINKER_FLAGS_RELEASE} /OPT:ICF")
 		set(BS_LINKER_FLAGS_RELEASE "${BS_LINKER_FLAGS_RELEASE} /OPT:ICF")
 	endif()
 	endif()