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

WIP Audio docs
Added a common FileReader class for all audio file readers

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

+ 1 - 0
Build/VS2015/BansheeOpenAudio.vcxproj

@@ -249,6 +249,7 @@
     </Link>
     </Link>
   </ItemDefinitionGroup>
   </ItemDefinitionGroup>
   <ItemGroup>
   <ItemGroup>
+    <ClInclude Include="..\..\Source\BansheeOpenAudio\Include\BsOAFileReader.h" />
     <ClInclude Include="..\..\Source\BansheeOpenAudio\Include\BsOAFLACReader.h" />
     <ClInclude Include="..\..\Source\BansheeOpenAudio\Include\BsOAFLACReader.h" />
     <ClInclude Include="..\..\Source\BansheeOpenAudio\Include\BsOAImporter.h" />
     <ClInclude Include="..\..\Source\BansheeOpenAudio\Include\BsOAImporter.h" />
     <ClInclude Include="..\..\Source\BansheeOpenAudio\Include\BsOAOggVorbisReader.h" />
     <ClInclude Include="..\..\Source\BansheeOpenAudio\Include\BsOAOggVorbisReader.h" />

+ 3 - 0
Build/VS2015/BansheeOpenAudio.vcxproj.filters

@@ -26,6 +26,9 @@
     <ClInclude Include="..\..\Source\BansheeOpenAudio\Include\BsOAFLACReader.h">
     <ClInclude Include="..\..\Source\BansheeOpenAudio\Include\BsOAFLACReader.h">
       <Filter>Header Files</Filter>
       <Filter>Header Files</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="..\..\Source\BansheeOpenAudio\Include\BsOAFileReader.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\Source\BansheeOpenAudio\Source\BsOAPlugin.cpp">
     <ClCompile Include="..\..\Source\BansheeOpenAudio\Source\BsOAPlugin.cpp">

+ 9 - 0
Source/BansheeCore/Include/BsAudio.h

@@ -11,11 +11,20 @@ namespace BansheeEngine
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
+	/** Provides global functionality relating to sounds and music. */
 	class BS_CORE_EXPORT Audio : public Module<Audio>
 	class BS_CORE_EXPORT Audio : public Module<Audio>
 	{
 	{
 	protected:
 	protected:
 		friend class AudioClip;
 		friend class AudioClip;
 
 
+		/** 
+		 * Creates a new audio clip.
+		 *
+		 * @param[in]	samples		Stream containing audio samples in format specified in @p desc.
+		 * @param[in]	numSamples	Number of samples in @p samples stream.
+		 * @param[in]	desc		Descriptor describing the type of the audio stream (format, sample rate, etc.).
+		 * @return					Newly created AudioClip. Must be manually initialized.
+		 */
 		virtual SPtr<AudioClip> createClip(const SPtr<DataStream>& samples, UINT32 numSamples, 
 		virtual SPtr<AudioClip> createClip(const SPtr<DataStream>& samples, UINT32 numSamples, 
 			const AUDIO_CLIP_DESC& desc) = 0;
 			const AUDIO_CLIP_DESC& desc) = 0;
 	};
 	};

+ 29 - 3
Source/BansheeCore/Include/BsAudioClip.h

@@ -11,28 +11,54 @@ namespace BansheeEngine
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
+	/** Valid internal engine audio formats. */
 	enum class AudioFormat
 	enum class AudioFormat
 	{
 	{
-		PCM,
-		VORBIS
+		PCM, /**< Pulse code modulation audio ("raw" uncompressed audio). */
+		VORBIS /**< Vorbis compressed audio. */
 	};
 	};
 
 
+	/** Modes that determine how and when is audio data read. */
 	enum class AudioReadMode
 	enum class AudioReadMode
 	{
 	{
-		LoadDecompressed,
+		/** Entire audio clip will be loaded and decompressed. Uses most memory but has lowest CPU impact. */
+		LoadDecompressed, 
+		/**
+		 * Entire audio clip will be loaded, but will be decompressed while playing. Uses medium amount of memory and has
+		 * the highest CPU impact. 
+		 */
 		LoadCompressed,
 		LoadCompressed,
+		/** 
+		 * Audio will be slowly streamed from the disk, and decompressed if needed. Uses very little memory, and has either
+		 * low or high CPU impact depending if the audio is in a compressed format. Since data is streamed from the disk,
+		 * read speeds could also be a bottleneck.
+		 */
 		Stream
 		Stream
 	};
 	};
 
 
+	/** Descriptor used for initializing an audio clip. */
 	struct AUDIO_CLIP_DESC
 	struct AUDIO_CLIP_DESC
 	{
 	{
+		/** Determines how is audio data read. */
 		AudioReadMode readMode = AudioReadMode::LoadDecompressed;
 		AudioReadMode readMode = AudioReadMode::LoadDecompressed;
+
+		/** Determines in which format is the audio data in. */
 		AudioFormat format = AudioFormat::PCM;
 		AudioFormat format = AudioFormat::PCM;
+
+		/** Sample rate (frequency) of the audio data. */
 		UINT32 frequency = 44100;
 		UINT32 frequency = 44100;
+
+		/** Number of bits per sample. Not used for compressed formats. */
 		UINT32 bitDepth = 16;
 		UINT32 bitDepth = 16;
+		
+		/** Number of channels. Each channel has its own step of samples. */
 		UINT32 numChannels = 2;
 		UINT32 numChannels = 2;
 	};
 	};
 
 
+	/** 
+	 * Audio clip stores audio data in a compressed or uncompressed format. Clips can be provided to audio sources or
+	 * or other audio methods to be played.
+	 */
 	class BS_CORE_EXPORT AudioClip : public Resource
 	class BS_CORE_EXPORT AudioClip : public Resource
 	{
 	{
 	public:
 	public:

+ 13 - 5
Source/BansheeOpenAudio/Include/BsOAFLACReader.h

@@ -3,6 +3,7 @@
 #pragma once
 #pragma once
 
 
 #include "BsOAPrerequisites.h"
 #include "BsOAPrerequisites.h"
+#include "BsOAFileReader.h"
 #include "FLAC\stream_decoder.h"
 #include "FLAC\stream_decoder.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
@@ -11,6 +12,7 @@ namespace BansheeEngine
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
+	/** Data used by the FLAC decoder. */
 	struct FLACDecoderData
 	struct FLACDecoderData
 	{
 	{
 		SPtr<DataStream> stream;
 		SPtr<DataStream> stream;
@@ -23,17 +25,23 @@ namespace BansheeEngine
 	};
 	};
 
 
 	/** Used for reading FLAC audio files. */
 	/** Used for reading FLAC audio files. */
-	class OAFLACReader
+	class OAFLACReader : public OAFileReader
 	{
 	{
 	public:
 	public:
 		OAFLACReader();
 		OAFLACReader();
 		~OAFLACReader();
 		~OAFLACReader();
 
 
-		bool open(const SPtr<DataStream>& stream, AudioFileInfo& info);
-		void seek(UINT32 offset); // Offset in number of samples
-		UINT32 read(UINT8* samples, UINT32 numSamples);
+		/** @copydoc OAFileReader::open */
+		bool open(const SPtr<DataStream>& stream, AudioFileInfo& info) override;
 
 
-		static bool isValid(const SPtr<DataStream>& stream);
+		/** @copydoc OAFileReader::seek */
+		void seek(UINT32 offset) override;
+
+		/** @copydoc OAFileReader::read */
+		UINT32 read(UINT8* samples, UINT32 numSamples) override;
+
+		/** @copydoc OAFileReader::isValid */
+		bool isValid(const SPtr<DataStream>& stream) override;
 	private:
 	private:
 		void close();
 		void close();
 
 

+ 54 - 0
Source/BansheeOpenAudio/Include/BsOAFileReader.h

@@ -0,0 +1,54 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsOAPrerequisites.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup OpenAudio
+	 *  @{
+	 */
+
+	/** Interface used for implementations that parse audio formats into a set of samples. */
+	class OAFileReader
+	{
+	public:
+		virtual ~OAFileReader() { }
+
+		/** 
+		 * Attempts to open audio data from the provided stream. Must be called before any reads or seeks. 
+		 *
+		 * @param[in]	stream	Data stream audio data is stored in.
+		 * @param[out]	info	Output information describing meta-data of the audio in the stream.
+		 * @return				True if the data is valid, false otherwise.
+		 */
+		virtual bool open(const SPtr<DataStream>& stream, AudioFileInfo& info) = 0;
+
+		/** 
+		 * Moves the read pointer to the specified offset. Any further read() calls will read from this location. User must
+		 * ensure not to seek past the end of the data.
+		 *
+		 * @param[in]	offset	Offset to move the pointer in. In number of samples.
+		 */
+		virtual void seek(UINT32 offset) = 0;
+
+		/**
+		 * Reads a set of samples from the audio data.
+		 *
+		 * @param[out]	samples		Pre-allocated buffer to store the samples in.
+		 * @param[in]	numSamples	Number of samples to read.
+		 * @return					Number of samples that were actually read (can be less than requested if the more data
+		 *							in the stream).
+		 */
+		virtual UINT32 read(UINT8* samples, UINT32 numSamples) = 0;
+
+		/** 
+		 * Checks if the data in the provided stream valid audio data for the current format. You should check this before
+		 * calling open().
+		 */
+		virtual bool isValid(const SPtr<DataStream>& stream) = 0;
+	};
+
+	/** @} */
+}

+ 12 - 5
Source/BansheeOpenAudio/Include/BsOAOggVorbisReader.h

@@ -3,6 +3,7 @@
 #pragma once
 #pragma once
 
 
 #include "BsOAPrerequisites.h"
 #include "BsOAPrerequisites.h"
+#include "BsOAFileReader.h"
 #include "vorbis\vorbisfile.h"
 #include "vorbis\vorbisfile.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
@@ -12,17 +13,23 @@ namespace BansheeEngine
 	 */
 	 */
 
 
 	/** Used for reading Ogg Vorbis audio files. */
 	/** Used for reading Ogg Vorbis audio files. */
-	class OAOggVorbisReader
+	class OAOggVorbisReader : public OAFileReader
 	{
 	{
 	public:
 	public:
 		OAOggVorbisReader();
 		OAOggVorbisReader();
 		~OAOggVorbisReader();
 		~OAOggVorbisReader();
 
 
-		bool open(const SPtr<DataStream>& stream, AudioFileInfo& info);
-		void seek(UINT32 offset); // Offset in number of samples
-		UINT32 read(UINT8* samples, UINT32 numSamples);
+		/** @copydoc OAFileReader::open */
+		bool open(const SPtr<DataStream>& stream, AudioFileInfo& info) override;
 
 
-		static bool isValid(const SPtr<DataStream>& stream);
+		/** @copydoc OAFileReader::read */
+		UINT32 read(UINT8* samples, UINT32 numSamples) override;
+
+		/** @copydoc OAFileReader::seek */
+		void seek(UINT32 offset) override;
+
+		/** @copydoc OAFileReader::isValid */
+		bool isValid(const SPtr<DataStream>& stream) override;
 	private:
 	private:
 		SPtr<DataStream> mStream;
 		SPtr<DataStream> mStream;
 		OggVorbis_File mOggVorbisFile;
 		OggVorbis_File mOggVorbisFile;

+ 12 - 5
Source/BansheeOpenAudio/Include/BsOAWaveReader.h

@@ -3,6 +3,7 @@
 #pragma once
 #pragma once
 
 
 #include "BsOAPrerequisites.h"
 #include "BsOAPrerequisites.h"
+#include "BsOAFileReader.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -11,16 +12,22 @@ namespace BansheeEngine
 	 */
 	 */
 
 
 	/** Used for reading .WAV audio files. */
 	/** Used for reading .WAV audio files. */
-	class OAWaveReader
+	class OAWaveReader : public OAFileReader
 	{
 	{
 	public:
 	public:
 		OAWaveReader();
 		OAWaveReader();
 
 
-		bool open(const SPtr<DataStream>& stream, AudioFileInfo& info);
-		void seek(UINT32 offset); // Offset in number of samples
-		UINT32 read(UINT8* samples, UINT32 numSamples);
+		/** @copydoc OAFileReader::open */
+		bool open(const SPtr<DataStream>& stream, AudioFileInfo& info) override;
 
 
-		static bool isValid(const SPtr<DataStream>& stream);
+		/** @copydoc OAFileReader::read */
+		UINT32 read(UINT8* samples, UINT32 numSamples) override;
+
+		/** @copydoc OAFileReader::seek */
+		void seek(UINT32 offset) override;
+
+		/** @copydoc OAFileReader::isValid */
+		bool isValid(const SPtr<DataStream>& stream) override;
 	private:
 	private:
 		bool parseHeader(AudioFileInfo& info);
 		bool parseHeader(AudioFileInfo& info);
 
 

+ 33 - 4
Source/BansheeOpenAudio/Source/BsOAImporter.cpp

@@ -3,6 +3,9 @@
 #include "BsOAImporter.h"
 #include "BsOAImporter.h"
 #include "BsDataStream.h"
 #include "BsDataStream.h"
 #include "BsFileSystem.h"
 #include "BsFileSystem.h"
+#include "BsOAWaveReader.h"
+#include "BsOAFLACReader.h"
+#include "BsOAOggVorbisReader.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -22,20 +25,46 @@ namespace BansheeEngine
 		WString lowerCaseExt = ext;
 		WString lowerCaseExt = ext;
 		StringUtil::toLowerCase(lowerCaseExt);
 		StringUtil::toLowerCase(lowerCaseExt);
 
 
-		// TODO
-		return false;
+		return lowerCaseExt == L"wav" || lowerCaseExt == L"flac" || lowerCaseExt == L"ogg";
 	}
 	}
 
 
 	bool OAImporter::isMagicNumberSupported(const UINT8* magicNumPtr, UINT32 numBytes) const
 	bool OAImporter::isMagicNumberSupported(const UINT8* magicNumPtr, UINT32 numBytes) const
 	{
 	{
-		// TODO
-		return true; // Plain-text so I don't even check for magic number
+		// Don't check for magic number, rely on extension
+		return true;
 	}
 	}
 
 
 	SPtr<Resource> OAImporter::import(const Path& filePath, SPtr<const ImportOptions> importOptions)
 	SPtr<Resource> OAImporter::import(const Path& filePath, SPtr<const ImportOptions> importOptions)
 	{
 	{
 		SPtr<DataStream> stream = FileSystem::openFile(filePath);
 		SPtr<DataStream> stream = FileSystem::openFile(filePath);
 
 
+		WString extension = filePath.getWExtension();
+		StringUtil::toLowerCase(extension);
+
+		// TODO - Respect import options and read mode
+		AudioFileInfo info;
+		UINT8* samples = nullptr;
+		if(extension == L"wav")
+		{
+			OAWaveReader reader;
+			if (!reader.isValid(stream))
+				return nullptr;
+
+			if (!reader.open(stream, info))
+				return nullptr;
+
+			//samples = bs_alloc(info.)
+			//reader.read()
+		}
+		else if(extension == L"flac")
+		{
+			
+		}
+		else if(extension == L"ogg")
+		{
+			
+		}
+
 		return nullptr;
 		return nullptr;
 	}
 	}
 }
 }