瀏覽代碼

Added support for on-the-fly decompression of Ogg Vorbis for FMOD audio sources
Reorganized OpenAudio decoders since they are now also used by FMOD audio implementation
Updated splash screen dimensions to match the new image

BearishSun 9 年之前
父節點
當前提交
74d115d38e

+ 2 - 2
Source/BansheeEngine/Source/BsSplashScreen.cpp

@@ -38,8 +38,8 @@ namespace BansheeEngine
 
 		WINDOW_DESC windowDesc;
 		windowDesc.border = WindowBorder::None;
-		windowDesc.width = 675;
-		windowDesc.height = 821;
+		windowDesc.width = 557;
+		windowDesc.height = 680;
 		windowDesc.left = -1;
 		windowDesc.top = -1;
 		windowDesc.title = "Banshee Splash";

+ 2 - 1
Source/BansheeFMOD/CMakeLists.txt

@@ -32,7 +32,8 @@ set_target_properties(FMOD PROPERTIES IMPORTED_LOCATION_RELEASE "${FMOD_LIBRARIE
 
 target_link_libraries(BansheeFMOD PRIVATE FMOD)	
 
-add_library_per_config(BansheeFMOD libvorbis libvorbis libvorbis)
+add_library_per_config_multi(BansheeFMOD libvorbis libvorbis libvorbis libvorbis)
+add_library_per_config_multi(BansheeFMOD libvorbisfile libvorbis libvorbisfile libvorbisfile)
 add_library_per_config(BansheeFMOD libogg Release/libogg Debug/libogg)
 
 ## Local libs

+ 5 - 2
Source/BansheeFMOD/CMakeSources.cmake

@@ -5,7 +5,9 @@ set(BS_BANSHEEFMOD_INC_NOFILTER
 	"Include/BsFMODAudioSource.h"
 	"Include/BsFMODAudioListener.h"
 	"Include/BsFMODAudioClip.h"
-	"../BansheeOpenAudio/Include/BsOggVorbisWriter.h"
+	"../BansheeOpenAudio/Include/BsOggVorbisEncoder.h"
+	"../BansheeOpenAudio/Include/BsAudioDecoder.h"
+	"../BansheeOpenAudio/Include/BsOggVorbisDecoder.h"
 )
 
 set(BS_BANSHEEFMOD_SRC_NOFILTER
@@ -15,7 +17,8 @@ set(BS_BANSHEEFMOD_SRC_NOFILTER
 	"Source/BsFMODAudioSource.cpp"
 	"Source/BsFMODAudioListener.cpp"
 	"Source/BsFMODAudioClip.cpp"
-	"../BansheeOpenAudio/Source/BsOggVorbisWriter.cpp"
+	"../BansheeOpenAudio/Source/BsOggVorbisEncoder.cpp"
+	"../BansheeOpenAudio/Source/BsOggVorbisDecoder.cpp"
 )
 
 source_group("Header Files" FILES ${BS_BANSHEEFMOD_INC_NOFILTER})

+ 19 - 1
Source/BansheeFMOD/Include/BsFMODAudioClip.h

@@ -4,6 +4,7 @@
 
 #include "BsFMODPrerequisites.h"
 #include "BsAudioClip.h"
+#include "BsOggVorbisDecoder.h"
 #include <fmod.hpp>
 
 namespace BansheeEngine
@@ -12,6 +13,14 @@ namespace BansheeEngine
 	 *  @{
 	 */
 	
+	/** Contains data used for decompressing an Ogg Vorbis stream. */
+	struct FMODOggDecompressorData
+	{
+		UINT32 readPos = 0;
+		OggVorbisDecoder vorbisReader;
+		const FMODAudioClip* clip = nullptr;
+	};
+
 	/** FMOD implementation of an AudioClip. */
 	class FMODAudioClip : public AudioClip
 	{
@@ -21,13 +30,22 @@ namespace BansheeEngine
 
 		/** 
 		 * Creates a new streaming sound. Only valid if the clip was created with AudioReadMode::Stream. Caller is
-		 * responsible for releasing the sound.
+		 * responsible for releasing the sound. Make sure to call releaseStreamingSound() when done.
 		 */
 		FMOD::Sound* createStreamingSound() const;
 
+		/** Releases any resources with a streaming sound (created with createStreamingSound()). */
+		static void releaseStreamingSound(FMOD::Sound* sound);
+
 		/** Returns FMOD sound representing this clip. Only valid for non-streaming clips. */
 		FMOD::Sound* getSound() const { return mSound; }
 
+		/** 
+		 * Checks whether the audio clip requires a streaming sound retrieved via createStreamingSound(), or can the 
+		 * basic sound retrieved via getSound() be used.
+		 */
+		bool requiresStreaming() const;
+
 	protected:
 		/** @copydoc Resource::initialize */
 		void initialize() override;

+ 157 - 34
Source/BansheeFMOD/Source/BsFMODAudioClip.cpp

@@ -6,6 +6,67 @@
 
 namespace BansheeEngine
 {
+	FMOD_RESULT F_CALLBACK pcmReadCallback(FMOD_SOUND* sound, void *data, unsigned int dataLen)
+	{
+		FMODOggDecompressorData* decompressor = nullptr;
+		((FMOD::Sound*)sound)->getUserData((void**)&decompressor);
+
+		const FMODAudioClip* clip = decompressor->clip;
+		UINT32 bytesPerSample = (clip->getBitDepth() / 8);
+
+		assert(dataLen % bytesPerSample == 0);
+		UINT32 numSamples = dataLen / bytesPerSample;
+
+		decompressor->vorbisReader.seek(decompressor->readPos);
+		UINT32 readSamples = decompressor->vorbisReader.read((UINT8*)data, numSamples);
+		while(readSamples < numSamples) // Looping
+		{
+			decompressor->vorbisReader.seek(0);
+
+			UINT8* writePtr = (UINT8*)data;
+			writePtr += readSamples * bytesPerSample;
+
+			readSamples += decompressor->vorbisReader.read(writePtr, numSamples - readSamples);
+		}
+
+		assert(readSamples == numSamples);
+
+		decompressor->readPos += readSamples;
+		decompressor->readPos %= clip->getNumSamples();
+
+		return FMOD_OK;
+	}
+
+	FMOD_RESULT F_CALLBACK pcmSetPosCallback(FMOD_SOUND* sound, int subsound, unsigned int position, FMOD_TIMEUNIT posType)
+	{
+		FMODOggDecompressorData* decompressor = nullptr;
+		((FMOD::Sound*)sound)->getUserData((void**)&decompressor);
+
+		const FMODAudioClip* clip = decompressor->clip;
+		UINT32 bytesPerSample = (clip->getBitDepth() / 8);
+
+		switch(posType)
+		{
+		case FMOD_TIMEUNIT_MS:
+			decompressor->readPos = (UINT32)((clip->getFrequency() * clip->getNumChannels()) * (position / 1000.0f));
+			break;
+		case FMOD_TIMEUNIT_PCM:
+			decompressor->readPos = clip->getNumChannels() * position;
+			break;
+		case FMOD_TIMEUNIT_PCMBYTES:
+			assert(position % bytesPerSample == 0);
+			decompressor->readPos = position / bytesPerSample;
+			break;
+		default:
+			LOGERR("Invalid time unit.");
+			break;
+		}
+
+		decompressor->readPos %= clip->getNumSamples();
+		decompressor->vorbisReader.seek(decompressor->readPos);
+		return FMOD_OK;
+	}
+
 	FMODAudioClip::FMODAudioClip(const SPtr<DataStream>& samples, UINT32 streamSize, UINT32 numSamples, const AUDIO_CLIP_DESC& desc)
 		:AudioClip(samples, streamSize, numSamples, desc), mSound(nullptr), mSourceStreamSize(0)
 	{ }
@@ -36,18 +97,9 @@ namespace BansheeEngine
 			mSourceStreamSize = mStreamSize;
 		}
 
-		FMOD::System* fmod = gFMODAudio()._getFMOD();
-		FMOD_MODE flags = FMOD_OPENMEMORY;
-
-		if (is3D())
-			flags |= FMOD_3D;
-		else
-			flags |= FMOD_2D;
-
-		// Load data into a sound buffer
-		if(mDesc.readMode == AudioReadMode::LoadDecompressed || mDesc.readMode == AudioReadMode::LoadCompressed)
+		// If streaming is not required, create the sound right away
+		if(!requiresStreaming())
 		{
-			// Read all data into memory
 			SPtr<DataStream> stream;
 			UINT32 offset = 0;
 			if (mSourceStreamData != nullptr) // If it's already loaded in memory, use it directly
@@ -61,24 +113,23 @@ namespace BansheeEngine
 			UINT32 bufferSize = info.numSamples * (info.bitDepth / 8);
 			UINT8* sampleBuffer = (UINT8*)bs_stack_alloc(bufferSize);
 
-			stream->seek(offset);
-			stream->read(sampleBuffer, bufferSize);
-
 			FMOD_CREATESOUNDEXINFO exInfo;
 			memset(&exInfo, 0, sizeof(exInfo));
 			exInfo.cbsize = sizeof(exInfo);
 			exInfo.length = bufferSize;
 
-			bool loadCompressed = mDesc.readMode == AudioReadMode::LoadCompressed && mDesc.format != AudioFormat::PCM;
+			FMOD_MODE flags = FMOD_CREATESAMPLE | FMOD_OPENMEMORY;
 
-			if (loadCompressed)
-				flags |= FMOD_CREATECOMPRESSEDSAMPLE;
+			if (is3D())
+				flags |= FMOD_3D;
 			else
-				flags |= FMOD_CREATESAMPLE;
+				flags |= FMOD_2D;
 
-			if(mDesc.format == AudioFormat::PCM)
+			if (mDesc.format == AudioFormat::PCM)
 			{
-				switch(mDesc.bitDepth)
+				flags |= FMOD_OPENRAW;
+
+				switch (mDesc.bitDepth)
 				{
 				case 8:
 					exInfo.format = FMOD_SOUND_FORMAT_PCM8;
@@ -99,11 +150,14 @@ namespace BansheeEngine
 
 				exInfo.numchannels = mDesc.numChannels;
 				exInfo.defaultfrequency = mDesc.frequency;
-
-				flags |= FMOD_OPENRAW;
 			}
 
-			if(fmod->createSound((const char*)sampleBuffer, flags, &exInfo, &mSound) != FMOD_OK)
+			sampleBuffer = (UINT8*)bs_stack_alloc(bufferSize);
+			stream->seek(offset);
+			stream->read(sampleBuffer, bufferSize);
+
+			FMOD::System* fmod = gFMODAudio()._getFMOD();
+			if (fmod->createSound((const char*)sampleBuffer, flags, &exInfo, &mSound) != FMOD_OK)
 			{
 				LOGERR("Failed creating sound.");
 			}
@@ -120,7 +174,23 @@ namespace BansheeEngine
 		}
 		else // Streaming
 		{
-			// Do nothing, we rely on AudioSource from creating sounds as only one streaming sound can ever be playing
+			// If reading from file, make a copy of data in memory, otherwise just take ownership of the existing buffer
+			if(mDesc.readMode == AudioReadMode::LoadCompressed && mStreamData->isFile())
+			{
+				if (mSourceStreamData != nullptr) // If it's already loaded in memory, use it directly
+					mStreamData = mSourceStreamData;
+				else
+				{
+					UINT8* data = (UINT8*)bs_alloc(mStreamSize);
+
+					mStreamData->seek(mStreamOffset);
+					mStreamData->read(data, mStreamSize);
+
+					mStreamData = bs_shared_ptr_new<MemoryDataStream>(data, mStreamSize);
+				}
+
+				mStreamOffset = 0;
+			}
 		}
 
 		AudioClip::initialize();
@@ -128,7 +198,7 @@ namespace BansheeEngine
 
 	FMOD::Sound* FMODAudioClip::createStreamingSound() const
 	{
-		if(getReadMode() != AudioReadMode::Stream || mStreamData == nullptr)
+		if(!requiresStreaming() || mStreamData == nullptr)
 		{
 			LOGERR("Invalid audio stream data.");
 			return nullptr;
@@ -144,6 +214,9 @@ namespace BansheeEngine
 		String pathStr;
 		if (mStreamData->isFile())
 		{
+			// initialize() guarantees the data was loaded in memory if it's not streaming
+			assert(mDesc.readMode == AudioReadMode::Stream);
+
 			exInfo.length = mStreamSize;
 			exInfo.fileoffset = mStreamOffset;
 
@@ -156,14 +229,46 @@ namespace BansheeEngine
 		{
 			SPtr<MemoryDataStream> memStream = std::static_pointer_cast<MemoryDataStream>(mStreamData);
 
-			// Note: I could use FMOD_OPENMEMORY_POINT here to save on memory, but then the caller would need to make
-			// sure the memory is not deallocated. I'm ignoring this for now as streaming from memory should be a rare
-			// occurence (normally only in editor)
-			flags |= FMOD_OPENMEMORY;
-			exInfo.length = mStreamSize;
+			if (mDesc.readMode == AudioReadMode::Stream)
+			{
+				// Note: I could use FMOD_OPENMEMORY_POINT here to save on memory, but then the caller would need to make
+				// sure the memory is not deallocated. I'm ignoring this for now as streaming from memory should be a rare
+				// occurence (normally only in editor)
+				flags |= FMOD_OPENMEMORY;
+
+				memStream->seek(mStreamOffset);
+				streamData = (const char*)memStream->getCurrentPtr();
+
+				exInfo.length = mStreamSize;
+			}
+			else // Load compressed
+			{
+				flags |= FMOD_OPENUSER;
 
-			memStream->seek(mStreamOffset);
-			streamData = (const char*)memStream->getCurrentPtr();
+				exInfo.decodebuffersize = mDesc.frequency;
+				exInfo.pcmreadcallback = pcmReadCallback;
+				exInfo.pcmsetposcallback = pcmSetPosCallback;
+
+				AudioDataInfo info;
+				info.bitDepth = mDesc.bitDepth;
+				info.numChannels = mDesc.numChannels;
+				info.numSamples = mNumSamples;
+				info.sampleRate = mDesc.frequency;
+
+				FMODOggDecompressorData* decompressorData = bs_new<FMODOggDecompressorData>();
+				decompressorData->clip = this;
+
+				if (!decompressorData->vorbisReader.open(memStream, info, mStreamOffset))
+				{
+					LOGERR("Failed decompressing AudioClip stream.");
+					return nullptr;
+				}
+
+				exInfo.userdata = decompressorData;
+				exInfo.length = mNumSamples * (mDesc.bitDepth / 8);
+
+				streamData = nullptr;
+			}
 		}
 
 		if (is3D())
@@ -171,7 +276,7 @@ namespace BansheeEngine
 		else
 			flags |= FMOD_2D;
 
-		if (mDesc.format == AudioFormat::PCM)
+		if (mDesc.format == AudioFormat::PCM || mDesc.readMode == AudioReadMode::LoadCompressed)
 		{
 			switch (mDesc.bitDepth)
 			{
@@ -195,7 +300,8 @@ namespace BansheeEngine
 			exInfo.numchannels = mDesc.numChannels;
 			exInfo.defaultfrequency = mDesc.frequency;
 
-			flags |= FMOD_OPENRAW;
+			if(mDesc.readMode != AudioReadMode::LoadCompressed)
+				flags |= FMOD_OPENRAW;
 		}
 
 		FMOD::Sound* sound = nullptr;
@@ -210,6 +316,17 @@ namespace BansheeEngine
 		return sound;
 	}
 
+	void FMODAudioClip::releaseStreamingSound(FMOD::Sound* sound)
+	{
+		FMODOggDecompressorData* decompressorData = nullptr;
+		((FMOD::Sound*)sound)->getUserData((void**)&decompressorData);
+
+		if (decompressorData != nullptr)
+			bs_delete(decompressorData);
+
+		sound->release();
+	}
+
 	SPtr<DataStream> FMODAudioClip::getSourceStream(UINT32& size)
 	{
 		size = mSourceStreamSize;
@@ -217,4 +334,10 @@ namespace BansheeEngine
 
 		return mSourceStreamData;
 	}
+
+	bool FMODAudioClip::requiresStreaming() const
+	{
+		return mDesc.readMode == AudioReadMode::Stream || 
+			(mDesc.readMode == AudioReadMode::LoadCompressed && mDesc.format == AudioFormat::VORBIS);
+	}
 }

+ 6 - 4
Source/BansheeFMOD/Source/BsFMODAudioSource.cpp

@@ -18,7 +18,7 @@ namespace BansheeEngine
 		gFMODAudio()._unregisterSource(this);
 
 		if (mStreamingSound != nullptr)
-			mStreamingSound->release();
+			FMODAudioClip::releaseStreamingSound(mStreamingSound);
 
 		if (mChannel != nullptr)
 			mChannel->stop();
@@ -103,7 +103,7 @@ namespace BansheeEngine
 			
 			FMODAudioClip* fmodClip = static_cast<FMODAudioClip*>(mAudioClip.get());
 			FMOD::Sound* sound;
-			if(mAudioClip->getReadMode() == AudioReadMode::Stream)
+			if(fmodClip->requiresStreaming())
 			{
 				mStreamingSound = fmodClip->createStreamingSound();
 				sound = mStreamingSound;
@@ -119,7 +119,7 @@ namespace BansheeEngine
 
 				if (mStreamingSound != nullptr)
 				{
-					mStreamingSound->release();
+					FMODAudioClip::releaseStreamingSound(mStreamingSound);
 					mStreamingSound = nullptr;
 				}
 
@@ -161,7 +161,9 @@ namespace BansheeEngine
 
 		if(mStreamingSound != nullptr)
 		{
-			mStreamingSound->release();
+			FMODAudioClip* fmodClip = static_cast<FMODAudioClip*>(mAudioClip.get());
+
+			FMODAudioClip::releaseStreamingSound(mStreamingSound);
 			mStreamingSound = nullptr;
 		}
 

+ 2 - 2
Source/BansheeFMOD/Source/BsFMODImporter.cpp

@@ -6,7 +6,7 @@
 #include "BsAudioClipImportOptions.h"
 #include "BsAudioUtility.h"
 #include "BsFMODAudio.h"
-#include "BsOggVorbisWriter.h"
+#include "BsOggVorbisEncoder.h"
 
 #include <fmod.hpp>
 
@@ -157,7 +157,7 @@ namespace BansheeEngine
 			// Note: If the original source was in Ogg Vorbis we could just copy it here, but instead we decode to PCM and
 			// then re-encode which is redundant. If later we decide to copy be aware that the engine encodes Ogg in a
 			// specific quality, and the the import source might have lower or higher bitrate/quality.
-			UINT8* encodedSamples = OggVorbisWriter::PCMToOggVorbis(sampleBuffer, info, bufferSize);
+			UINT8* encodedSamples = OggVorbisEncoder::PCMToOggVorbis(sampleBuffer, info, bufferSize);
 
 			bs_free(sampleBuffer);
 			sampleBuffer = encodedSamples;

+ 9 - 9
Source/BansheeOpenAudio/CMakeSources.cmake

@@ -1,11 +1,11 @@
 set(BS_BANSHEEOPENAUDIO_INC_NOFILTER
 	"Include/BsOAPrerequisites.h"
 	"Include/BsOAImporter.h"
-	"Include/BsOAWaveReader.h"
-	"Include/BsOAOggVorbisReader.h"
-	"Include/BsOAFLACReader.h"
-	"Include/BsOAFileReader.h"
-	"Include/BsOggVorbisWriter.h"
+	"Include/BsWaveDecoder.h"
+	"Include/BsOggVorbisDecoder.h"
+	"Include/BsFLACDecoder.h"
+	"Include/BsAudioDecoder.h"
+	"Include/BsOggVorbisEncoder.h"
 	"Include/BsOAAudioClip.h"
 	"Include/BsOAAudio.h"
 	"Include/BsOAAudioSource.h"
@@ -15,10 +15,10 @@ set(BS_BANSHEEOPENAUDIO_INC_NOFILTER
 set(BS_BANSHEEOPENAUDIO_SRC_NOFILTER
 	"Source/BsOAPlugin.cpp"
 	"Source/BsOAImporter.cpp"
-	"Source/BsOAWaveReader.cpp"
-	"Source/BsOAOggVorbisReader.cpp"
-	"Source/BsOAFLACReader.cpp"
-	"Source/BsOggVorbisWriter.cpp"
+	"Source/BsWaveDecoder.cpp"
+	"Source/BsOggVorbisDecoder.cpp"
+	"Source/BsFLACDecoder.cpp"
+	"Source/BsOggVorbisEncoder.cpp"
 	"Source/BsOAAudioClip.cpp"
 	"Source/BsOAAudio.cpp"
 	"Source/BsOAAudioSource.cpp"

+ 3 - 3
Source/BansheeOpenAudio/Include/BsOAFileReader.h → Source/BansheeOpenAudio/Include/BsAudioDecoder.h

@@ -10,11 +10,11 @@ namespace BansheeEngine
 	 *  @{
 	 */
 
-	/** Interface used for implementations that parse audio formats into a set of samples. */
-	class OAFileReader
+	/** Interface used for implementations that parse audio formats into a set of PCM samples. */
+	class AudioDecoder
 	{
 	public:
-		virtual ~OAFileReader() { }
+		virtual ~AudioDecoder() { }
 
 		/** 
 		 * Attempts to open audio data from the provided stream. Must be called before any reads or seeks. 

+ 5 - 5
Source/BansheeOpenAudio/Include/BsOAFLACReader.h → Source/BansheeOpenAudio/Include/BsFLACDecoder.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsOAPrerequisites.h"
-#include "BsOAFileReader.h"
+#include "BsAudioDecoder.h"
 #include "FLAC\stream_decoder.h"
 
 namespace BansheeEngine
@@ -24,12 +24,12 @@ namespace BansheeEngine
 		bool error = false;
 	};
 
-	/** Used for reading FLAC audio data. */
-	class OAFLACReader : public OAFileReader
+	/** Decodes FLAC audio data into raw PCM samples. */
+	class FLACDecoder : public AudioDecoder
 	{
 	public:
-		OAFLACReader();
-		~OAFLACReader();
+		FLACDecoder();
+		~FLACDecoder();
 
 		/** @copydoc OAFileReader::open */
 		bool open(const SPtr<DataStream>& stream, AudioDataInfo& info, UINT32 offset = 0) override;

+ 2 - 2
Source/BansheeOpenAudio/Include/BsOAAudioClip.h

@@ -4,7 +4,7 @@
 
 #include "BsOAPrerequisites.h"
 #include "BsAudioClip.h"
-#include "BsOAOggVorbisReader.h"
+#include "BsOggVorbisDecoder.h"
 
 namespace BansheeEngine
 {
@@ -49,7 +49,7 @@ namespace BansheeEngine
 		SPtr<DataStream> getSourceStream(UINT32& size) override;
 	private:
 		mutable Mutex mMutex;
-		mutable OAOggVorbisReader mVorbisReader;
+		mutable OggVorbisDecoder mVorbisReader;
 		bool mNeedsDecompression;
 		UINT32 mBufferId;
 

+ 4 - 4
Source/BansheeOpenAudio/Include/BsOAOggVorbisReader.h → Source/BansheeOpenAudio/Include/BsOggVorbisDecoder.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsOAPrerequisites.h"
-#include "BsOAFileReader.h"
+#include "BsAudioDecoder.h"
 #include "vorbis\vorbisfile.h"
 
 namespace BansheeEngine
@@ -24,11 +24,11 @@ namespace BansheeEngine
 	};
 
 	/** Used for reading Ogg Vorbis audio data. */
-	class OAOggVorbisReader : public OAFileReader
+	class OggVorbisDecoder : public AudioDecoder
 	{
 	public:
-		OAOggVorbisReader();
-		~OAOggVorbisReader();
+		OggVorbisDecoder();
+		~OggVorbisDecoder();
 
 		/** @copydoc OAFileReader::open */
 		bool open(const SPtr<DataStream>& stream, AudioDataInfo& info, UINT32 offset = 0) override;

+ 3 - 3
Source/BansheeOpenAudio/Include/BsOggVorbisWriter.h → Source/BansheeOpenAudio/Include/BsOggVorbisEncoder.h

@@ -12,11 +12,11 @@ namespace BansheeEngine
 	 */
 
 	/** Used for encoding PCM to Ogg Vorbis audio data. */
-	class OggVorbisWriter
+	class OggVorbisEncoder
 	{
 	public:
-		OggVorbisWriter();
-		~OggVorbisWriter();
+		OggVorbisEncoder();
+		~OggVorbisEncoder();
 
 		/** 
 		 * Sets up the writer. Should be called before calling write(). 

+ 4 - 4
Source/BansheeOpenAudio/Include/BsOAWaveReader.h → Source/BansheeOpenAudio/Include/BsWaveDecoder.h

@@ -3,7 +3,7 @@
 #pragma once
 
 #include "BsOAPrerequisites.h"
-#include "BsOAFileReader.h"
+#include "BsAudioDecoder.h"
 
 namespace BansheeEngine
 {
@@ -11,11 +11,11 @@ namespace BansheeEngine
 	 *  @{
 	 */
 
-	/** Used for reading .WAV audio files. */
-	class OAWaveReader : public OAFileReader
+	/** Decodes .WAV audio data into raw PCM format. */
+	class WaveDecoder : public AudioDecoder
 	{
 	public:
-		OAWaveReader();
+		WaveDecoder();
 
 		/** @copydoc OAFileReader::open */
 		bool open(const SPtr<DataStream>& stream, AudioDataInfo& info, UINT32 offset = 0) override;

+ 8 - 8
Source/BansheeOpenAudio/Source/BsOAFLACReader.cpp → Source/BansheeOpenAudio/Source/BsFLACDecoder.cpp

@@ -1,6 +1,6 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsOAFLACReader.h"
+#include "BsFLACDecoder.h"
 #include "BsDataStream.h"
 
 namespace BansheeEngine
@@ -128,16 +128,16 @@ namespace BansheeEngine
 		data->error = true;
 	}
 
-	OAFLACReader::OAFLACReader()
+	FLACDecoder::FLACDecoder()
 		:mDecoder(nullptr)
 	{ }
 
-	OAFLACReader::~OAFLACReader()
+	FLACDecoder::~FLACDecoder()
 	{
 		close();
 	}
 
-	bool OAFLACReader::isValid(const SPtr<DataStream>& stream, UINT32 offset)
+	bool FLACDecoder::isValid(const SPtr<DataStream>& stream, UINT32 offset)
 	{
 		stream->seek(offset);
 
@@ -159,7 +159,7 @@ namespace BansheeEngine
 		return valid && !data.error;
 	}
 
-	bool OAFLACReader::open(const SPtr<DataStream>& stream, AudioDataInfo& info, UINT32 offset)
+	bool FLACDecoder::open(const SPtr<DataStream>& stream, AudioDataInfo& info, UINT32 offset)
 	{
 		if (stream == nullptr)
 			return false;
@@ -190,7 +190,7 @@ namespace BansheeEngine
 		return true;
 	}
 
-	void OAFLACReader::seek(UINT32 offset)
+	void FLACDecoder::seek(UINT32 offset)
 	{
 		mData.output = nullptr;
 		mData.samplesToRead = 0;
@@ -199,7 +199,7 @@ namespace BansheeEngine
 		FLAC__stream_decoder_seek_absolute(mDecoder, offset);
 	}
 
-	UINT32 OAFLACReader::read(UINT8* samples, UINT32 numSamples)
+	UINT32 FLACDecoder::read(UINT8* samples, UINT32 numSamples)
 	{
 		UINT32 overflowSize = (UINT32)mData.overflow.size();
 		UINT32 overflowNumSamples = 0;
@@ -237,7 +237,7 @@ namespace BansheeEngine
 		return numSamples - mData.samplesToRead;
 	}
 
-	void OAFLACReader::close()
+	void FLACDecoder::close()
 	{
 		if (mDecoder != nullptr)
 		{

+ 3 - 3
Source/BansheeOpenAudio/Source/BsOAAudioClip.cpp

@@ -1,8 +1,8 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "BsOAAudioClip.h"
-#include "BsOggVorbisWriter.h"
-#include "BsOAOggVorbisReader.h"
+#include "BsOggVorbisEncoder.h"
+#include "BsOggVorbisDecoder.h"
 #include "BsDataStream.h"
 #include "BsOAAudio.h"
 #include "AL/al.h"
@@ -67,7 +67,7 @@ namespace BansheeEngine
 				// Decompress from Ogg
 				if (mDesc.format == AudioFormat::VORBIS)
 				{
-					OAOggVorbisReader reader;
+					OggVorbisDecoder reader;
 					if (reader.open(stream, info, offset))
 						reader.read(sampleBuffer, info.numSamples);
 					else

+ 9 - 9
Source/BansheeOpenAudio/Source/BsOAImporter.cpp

@@ -3,10 +3,10 @@
 #include "BsOAImporter.h"
 #include "BsDataStream.h"
 #include "BsFileSystem.h"
-#include "BsOAWaveReader.h"
-#include "BsOAFLACReader.h"
-#include "BsOAOggVorbisReader.h"
-#include "BsOggVorbisWriter.h"
+#include "BsWaveDecoder.h"
+#include "BsFLACDecoder.h"
+#include "BsOggVorbisDecoder.h"
+#include "BsOggVorbisEncoder.h"
 #include "BsAudioClipImportOptions.h"
 #include "BsAudioUtility.h"
 
@@ -49,13 +49,13 @@ namespace BansheeEngine
 		WString extension = filePath.getWExtension();
 		StringUtil::toLowerCase(extension);
 
-		UPtr<OAFileReader> reader(nullptr, nullptr);
+		UPtr<AudioDecoder> reader(nullptr, nullptr);
 		if(extension == L".wav")
-			reader = bs_unique_ptr<OAFileReader>(bs_new<OAWaveReader>());
+			reader = bs_unique_ptr<AudioDecoder>(bs_new<WaveDecoder>());
 		else if(extension == L".flac")
-			reader = bs_unique_ptr<OAFileReader>(bs_new<OAFLACReader>());
+			reader = bs_unique_ptr<AudioDecoder>(bs_new<FLACDecoder>());
 		else if(extension == L".ogg")
-			reader = bs_unique_ptr<OAFileReader>(bs_new<OAOggVorbisReader>());
+			reader = bs_unique_ptr<AudioDecoder>(bs_new<OggVorbisDecoder>());
 
 		if (reader == nullptr)
 			return nullptr;
@@ -115,7 +115,7 @@ namespace BansheeEngine
 			// Note: If the original source was in Ogg Vorbis we could just copy it here, but instead we decode to PCM and
 			// then re-encode which is redundant. If later we decide to copy be aware that the engine encodes Ogg in a
 			// specific quality, and the the import source might have lower or higher bitrate/quality.
-			UINT8* encodedSamples = OggVorbisWriter::PCMToOggVorbis(sampleBuffer, info, bufferSize);
+			UINT8* encodedSamples = OggVorbisEncoder::PCMToOggVorbis(sampleBuffer, info, bufferSize);
 
 			bs_free(sampleBuffer);
 			sampleBuffer = encodedSamples;

+ 7 - 7
Source/BansheeOpenAudio/Source/BsOAOggVorbisReader.cpp → Source/BansheeOpenAudio/Source/BsOggVorbisDecoder.cpp

@@ -1,6 +1,6 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsOAOggVorbisReader.h"
+#include "BsOggVorbisDecoder.h"
 #include "BsDataStream.h"
 #include <vorbis\codec.h>
 
@@ -40,19 +40,19 @@ namespace BansheeEngine
 
 	static ov_callbacks callbacks = { &oggRead, &oggSeek, nullptr, &oggTell };
 
-	OAOggVorbisReader::OAOggVorbisReader()
+	OggVorbisDecoder::OggVorbisDecoder()
 		:mChannelCount(0)
 	{
 		mOggVorbisFile.datasource = nullptr;
 	}
 
-	OAOggVorbisReader::~OAOggVorbisReader()
+	OggVorbisDecoder::~OggVorbisDecoder()
 	{
 		if (mOggVorbisFile.datasource != nullptr)
 			ov_clear(&mOggVorbisFile);
 	}
 
-	bool OAOggVorbisReader::isValid(const SPtr<DataStream>& stream, UINT32 offset)
+	bool OggVorbisDecoder::isValid(const SPtr<DataStream>& stream, UINT32 offset)
 	{
 		stream->seek(offset);
 		mDecoderData.stream = stream;
@@ -68,7 +68,7 @@ namespace BansheeEngine
 		return false;
 	}
 
-	bool OAOggVorbisReader::open(const SPtr<DataStream>& stream, AudioDataInfo& info, UINT32 offset)
+	bool OggVorbisDecoder::open(const SPtr<DataStream>& stream, AudioDataInfo& info, UINT32 offset)
 	{
 		if (stream == nullptr)
 			return false;
@@ -94,12 +94,12 @@ namespace BansheeEngine
 		return true;
 	}
 
-	void OAOggVorbisReader::seek(UINT32 offset)
+	void OggVorbisDecoder::seek(UINT32 offset)
 	{
 		ov_pcm_seek(&mOggVorbisFile, offset / mChannelCount);
 	}
 
-	UINT32 OAOggVorbisReader::read(UINT8* samples, UINT32 numSamples)
+	UINT32 OggVorbisDecoder::read(UINT8* samples, UINT32 numSamples)
 	{
 		UINT32 numReadSamples = 0;
 		while (numReadSamples < numSamples)

+ 11 - 10
Source/BansheeOpenAudio/Source/BsOggVorbisWriter.cpp → Source/BansheeOpenAudio/Source/BsOggVorbisEncoder.cpp

@@ -1,4 +1,4 @@
-#include "BsOggVorbisWriter.h"
+#include "BsOggVorbisEncoder.h"
 #include "BsDataStream.h"
 #include "BsAudioUtility.h"
 
@@ -17,21 +17,22 @@ namespace BansheeEngine
 		mBufferOffset += length;						\
 	}
 
-	OggVorbisWriter::OggVorbisWriter()
+	OggVorbisEncoder::OggVorbisEncoder()
 		:mBufferOffset(0), mNumChannels(0), mBitDepth(0), mClosed(true)
 	{ }
 
-	OggVorbisWriter::~OggVorbisWriter()
+	OggVorbisEncoder::~OggVorbisEncoder()
 	{
 		close();
 	}
 
-	bool OggVorbisWriter::open(std::function<void(UINT8*, UINT32)> writeCallback, UINT32 sampleRate, UINT32 bitDepth, 
+	bool OggVorbisEncoder::open(std::function<void(UINT8*, UINT32)> writeCallback, UINT32 sampleRate, UINT32 bitDepth, 
 		UINT32 numChannels)
 	{
 		mNumChannels = numChannels;
 		mBitDepth = bitDepth;
 		mWriteCallback = writeCallback;
+		mClosed = false;
 
 		ogg_stream_init(&mOggState, std::rand());
 		vorbis_info_init(&mVorbisInfo);
@@ -78,7 +79,7 @@ namespace BansheeEngine
 		return true;
 	}
 
-	void OggVorbisWriter::write(UINT8* samples, UINT32 numSamples)
+	void OggVorbisEncoder::write(UINT8* samples, UINT32 numSamples)
 	{
 		static const UINT32 WRITE_LENGTH = 1024;
 
@@ -155,7 +156,7 @@ namespace BansheeEngine
 		}
 	}
 
-	void OggVorbisWriter::writeBlocks()
+	void OggVorbisEncoder::writeBlocks()
 	{
 		while (vorbis_analysis_blockout(&mVorbisState, &mVorbisBlock) == 1)
 		{
@@ -180,7 +181,7 @@ namespace BansheeEngine
 		}
 	}
 
-	void OggVorbisWriter::flush()
+	void OggVorbisEncoder::flush()
 	{
 		if (mBufferOffset > 0 && mWriteCallback != nullptr)
 			mWriteCallback(mBuffer, mBufferOffset);
@@ -188,7 +189,7 @@ namespace BansheeEngine
 		mBufferOffset = 0;
 	}
 
-	void OggVorbisWriter::close()
+	void OggVorbisEncoder::close()
 	{
 		if (mClosed)
 			return;
@@ -206,7 +207,7 @@ namespace BansheeEngine
 		mClosed = true;
 	}
 
-	UINT8* OggVorbisWriter::PCMToOggVorbis(UINT8* samples, const AudioDataInfo& info, UINT32& size)
+	UINT8* OggVorbisEncoder::PCMToOggVorbis(UINT8* samples, const AudioDataInfo& info, UINT32& size)
 	{
 		struct EncodedBlock
 		{
@@ -229,7 +230,7 @@ namespace BansheeEngine
 
 		bs_frame_mark();
 
-		OggVorbisWriter writer;
+		OggVorbisEncoder writer;
 		writer.open(writeCallback, info.sampleRate, info.bitDepth, info.numChannels);
 
 		writer.write(samples, info.numSamples);

+ 7 - 7
Source/BansheeOpenAudio/Source/BsOAWaveReader.cpp → Source/BansheeOpenAudio/Source/BsWaveDecoder.cpp

@@ -1,6 +1,6 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsOAWaveReader.h"
+#include "BsWaveDecoder.h"
 #include "BsDataStream.h"
 
 namespace BansheeEngine
@@ -8,11 +8,11 @@ namespace BansheeEngine
 #define WAVE_FORMAT_PCM			0x0001
 #define WAVE_FORMAT_EXTENDED	0xFFFE
 
-	OAWaveReader::OAWaveReader()
+	WaveDecoder::WaveDecoder()
 		:mDataOffset(0), mBytesPerSample(0)
 	{ }
 
-	bool OAWaveReader::isValid(const SPtr<DataStream>& stream, UINT32 offset)
+	bool WaveDecoder::isValid(const SPtr<DataStream>& stream, UINT32 offset)
 	{
 		stream->seek(offset);
 
@@ -24,7 +24,7 @@ namespace BansheeEngine
 			&& (header[8] == 'W') && (header[9] == 'A') && (header[10] == 'V') && (header[11] == 'E');
 	}
 
-	bool OAWaveReader::open(const SPtr<DataStream>& stream, AudioDataInfo& info, UINT32 offset)
+	bool WaveDecoder::open(const SPtr<DataStream>& stream, AudioDataInfo& info, UINT32 offset)
 	{
 		if (stream == nullptr)
 			return false;
@@ -41,12 +41,12 @@ namespace BansheeEngine
 		return true;
 	}
 
-	void OAWaveReader::seek(UINT32 offset)
+	void WaveDecoder::seek(UINT32 offset)
 	{
 		mStream->seek(mDataOffset + offset * mBytesPerSample);
 	}
 
-	UINT32 OAWaveReader::read(UINT8* samples, UINT32 numSamples)
+	UINT32 WaveDecoder::read(UINT8* samples, UINT32 numSamples)
 	{
 		UINT32 numRead = (UINT32)mStream->read(samples, numSamples * mBytesPerSample);
 
@@ -62,7 +62,7 @@ namespace BansheeEngine
 		return numRead;
 	}
 
-	bool OAWaveReader::parseHeader(AudioDataInfo& info)
+	bool WaveDecoder::parseHeader(AudioDataInfo& info)
 	{
 		bool foundData = false;
 		while (!foundData)