Prechádzať zdrojové kódy

Moved mono and bit depth conversion to AudioUtility class

BearishSun 9 rokov pred
rodič
commit
1fa8d1d106

+ 2 - 0
Source/BansheeCore/CMakeSources.cmake

@@ -473,6 +473,7 @@ set(BS_BANSHEECORE_INC_AUDIO
 	"Include/BsAudioListener.h"
 	"Include/BsAudioSource.h"
 	"Include/BsAudioClipImportOptions.h"
+	"Include/BsAudioUtility.h"
 )
 
 set(BS_BANSHEECORE_SRC_AUDIO
@@ -481,6 +482,7 @@ set(BS_BANSHEECORE_SRC_AUDIO
 	"Source/BsAudioListener.cpp"
 	"Source/BsAudioSource.cpp"
 	"Source/BsAudioClipImportOptions.cpp"
+	"Source/BsAudioUtility.cpp"
 )
 
 source_group("Header Files\\Components" FILES ${BS_BANSHEECORE_INC_COMPONENTS})

+ 46 - 0
Source/BansheeCore/Include/BsAudioUtility.h

@@ -0,0 +1,46 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup Audio
+	 *  @{
+	 */
+
+	/** Provides various utility functionality relating to audio. */
+	class BS_CORE_EXPORT AudioUtility
+	{
+	public:
+		/** 
+		 * Converts a set of audio samples using multiple channels into a set of mono samples. 
+		 *
+		 * @param[in]	input		A set of input samples. Per-channels samples should be interleaved. Size of each sample
+		 *							is determined by @p bitDepth. Total size of the buffer should be @p numSamples *
+		 *							@p numChannels * @p bitDepth / 8.
+		 * @param[out]	output		Pre-allocated buffer to store the mono samples. Should be of @p numSamples * 
+		 *							@p bitDepth / 8 size.
+		 * @param[in]	bitDepth	Size of a single sample in bits.
+		 * @param[in]	numSamples	Number of samples per a single channel.
+		 * @param[in]	numChannels	Number of channels in the input data.
+		 */
+		static void convertToMono(UINT8* input, UINT8* output, UINT32 bitDepth, UINT32 numSamples, UINT32 numChannels);
+
+		/**
+		 * Converts a set of audio samples of a certain bit depth to a new bit depth.
+		 *
+		 * @param[in]	input		A set of input samples. Total size of the buffer should be @p numSamples *
+		 *							@p inBitDepth / 8.
+		 * @param[in]	inBitDepth	Size of a single sample in the @p input array, in bits.
+		 * @param[out]	output		Pre-allocated buffer to store the output samples in. Total size of the buffer should be
+		 *							@p numSamples * @p outBitDepth / 8.
+		 * @param[in]	inBitDepth	Size of a single sample in the @p output array, in bits.
+		 * @param[in]	numSamples	Total number of samples to process.
+		 */
+		static void convertBitDepth(UINT8* input, UINT32 inBitDepth, UINT8* output, UINT32 outBitDepth, UINT32 numSamples);
+	};
+
+	/** @} */
+}

+ 216 - 0
Source/BansheeCore/Source/BsAudioUtility.cpp

@@ -0,0 +1,216 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsAudioUtility.h"
+
+namespace BansheeEngine
+{
+	void convertToMono8(UINT8* input, UINT8* output, UINT32 numSamples, UINT32 numChannels)
+	{
+		for (UINT32 i = 0; i < numSamples; i++)
+		{
+			UINT16 sum = 0;
+			for (UINT32 j = 0; j < numChannels; j++)
+			{
+				sum += *input;
+				++input;
+			}
+
+			*output = sum / numChannels;
+			++output;
+		}
+	}
+
+	void convertToMono16(INT16* input, INT16* output, UINT32 numSamples, UINT32 numChannels)
+	{
+		for (UINT32 i = 0; i < numSamples; i++)
+		{
+			INT32 sum = 0;
+			for (UINT32 j = 0; j < numChannels; j++)
+			{
+				sum += *input;
+				++input;
+			}
+
+			*output = sum / numChannels;
+			++output;
+		}
+	}
+
+	INT32 convert24To32Bits(const UINT8* input)
+	{
+		bool isNegative = (input[2] & 0x80) != 0;
+		if (isNegative) // Sign extend if negative
+			return (0xFF << 24) | (input[2] << 16) | (input[1] << 8) | input[0];
+		else
+			return (input[2] << 16) | (input[1] << 8) | input[0];
+	}
+
+	void convert32To24Bits(INT32 input, UINT8* output)
+	{
+		UINT32 valToEncode = *(UINT32*)&input;
+		output[0] = valToEncode & 0x000000FF;
+		output[1] = (valToEncode >> 8) & 0x000000FF;
+		output[2] = (valToEncode >> 16) & 0x000000FF;
+	}
+
+	void convertToMono24(UINT8* input, UINT8* output, UINT32 numSamples, UINT32 numChannels)
+	{
+		for (UINT32 i = 0; i < numSamples; i++)
+		{
+			INT32 sum = 0;
+			for (UINT32 j = 0; j < numChannels; j++)
+			{
+				sum += convert24To32Bits(input);
+				input += 3;
+			}
+
+			INT32 avg = sum / numChannels;
+			convert32To24Bits(avg, output);
+			output += 3;
+		}
+	}
+
+	void convertToMono32(INT32* input, INT32* output, UINT32 numSamples, UINT32 numChannels)
+	{
+		for (UINT32 i = 0; i < numSamples; i++)
+		{
+			INT64 sum = 0;
+			for (UINT32 j = 0; j < numChannels; j++)
+			{
+				sum += *input;
+				++input;
+			}
+
+			*output = (INT32)(sum / numChannels);
+			++output;
+		}
+	}
+
+	void convert8To32Bits(UINT8* input, INT32* output, UINT32 numSamples)
+	{
+		for (UINT32 i = 0; i < numSamples; i++)
+		{
+			INT8 val = (INT8)(input[i] - 128);
+			output[i] = val << 24;
+		}
+	}
+
+	void convert16To32Bits(INT16* input, INT32* output, UINT32 numSamples)
+	{
+		for (UINT32 i = 0; i < numSamples; i++)
+			output[i] = input[i] << 16;
+	}
+
+	void convert24To32Bits(UINT8* input, INT32* output, UINT32 numSamples)
+	{
+		for (UINT32 i = 0; i < numSamples; i++)
+		{
+			output[i] = convert24To32Bits(input);
+			input += 3;
+		}
+	}
+
+	void convert32To8Bits(INT32* input, UINT8* output, UINT32 numSamples)
+	{
+		for (UINT32 i = 0; i < numSamples; i++)
+		{
+			INT8 val = (INT8)(input[i] >> 24);
+			output[i] = (UINT8)(val + 128);
+		}
+	}
+
+	void convert32To16Bits(INT32* input, INT16* output, UINT32 numSamples)
+	{
+		for (UINT32 i = 0; i < numSamples; i++)
+			output[i] = (INT16)(input[i] >> 16);
+	}
+
+	void convert32To24Bits(INT32* input, UINT8* output, UINT32 numSamples)
+	{
+		for (UINT32 i = 0; i < numSamples; i++)
+		{
+			convert32To24Bits(input[i], output);
+			output += 3;
+		}
+	}
+
+	void AudioUtility::convertToMono(UINT8* input, UINT8* output, UINT32 bitDepth, UINT32 numSamples, UINT32 numChannels)
+	{
+		switch (bitDepth)
+		{
+		case 8:
+			convertToMono8(input, output, numSamples, numChannels);
+			break;
+		case 16:
+			convertToMono16((INT16*)input, (INT16*)output, numSamples, numChannels);
+			break;
+		case 24:
+			convertToMono24(input, output, numSamples, numChannels);
+			break;
+		case 32:
+			convertToMono32((INT32*)input, (INT32*)output, numSamples, numChannels);
+			break;
+		default:
+			assert(false);
+			break;
+		}
+	}
+
+	void AudioUtility::convertBitDepth(UINT8* input, UINT32 inBitDepth, UINT8* output, UINT32 outBitDepth, UINT32 numSamples)
+	{
+		INT32* srcBuffer = nullptr;
+
+		bool needTempBuffer = inBitDepth != 32;
+		if (needTempBuffer)
+			srcBuffer = (INT32*)bs_stack_alloc(numSamples * sizeof(INT32));
+		else
+			srcBuffer = (INT32*)input;
+
+		// Note: I convert to a temporary 32-bit buffer and then use that to convert to actual requested bit depth. 
+		//       It would be more efficient to convert directly from source to requested depth without a temporary buffer,
+		//       at the cost of additional complexity. If this method ever becomes a performance issue consider that.
+		switch (inBitDepth)
+		{
+		case 8:
+			convert8To32Bits(input, srcBuffer, numSamples);
+			break;
+		case 16:
+			convert16To32Bits((INT16*)input, srcBuffer, numSamples);
+			break;
+		case 24:
+			convert8To32Bits(input, srcBuffer, numSamples);
+			break;
+		case 32:
+			// Do nothing
+			break;
+		default:
+			assert(false);
+			break;
+		}
+
+		switch (outBitDepth)
+		{
+		case 8:
+			convert32To8Bits(srcBuffer, output, numSamples);
+			break;
+		case 16:
+			convert32To16Bits(srcBuffer, (INT16*)output, numSamples);
+			break;
+		case 24:
+			convert32To24Bits(srcBuffer, output, numSamples);
+			break;
+		case 32:
+			memcpy(output, srcBuffer, numSamples * sizeof(INT32));
+			break;
+		default:
+			assert(false);
+			break;
+		}
+
+		if (needTempBuffer)
+		{
+			bs_stack_free(srcBuffer);
+			srcBuffer = nullptr;
+		}
+	}
+}

+ 3 - 211
Source/BansheeOpenAudio/Source/BsOAImporter.cpp

@@ -8,197 +8,10 @@
 #include "BsOAOggVorbisReader.h"
 #include "BsOAOggVorbisWriter.h"
 #include "BsAudioClipImportOptions.h"
+#include "BsAudioUtility.h"
 
 namespace BansheeEngine
 {
-	void convertToMono8(UINT8* input, UINT8* output, UINT32 numSamples, UINT32 numChannels)
-	{
-		for (UINT32 i = 0; i < numSamples; i++)
-		{
-			UINT16 sum = 0;
-			for (UINT32 j = 0; j < numChannels; j++)
-			{
-				sum += *input;
-				++input;
-			}
-
-			*output = sum / numChannels;
-			++output;
-		}
-	}
-
-	void convertToMono16(INT16* input, INT16* output, UINT32 numSamples, UINT32 numChannels)
-	{
-		for (UINT32 i = 0; i < numSamples; i++)
-		{
-			INT32 sum = 0;
-			for (UINT32 j = 0; j < numChannels; j++)
-			{
-				sum += *input;
-				++input;
-			}
-
-			*output = sum / numChannels;
-			++output;
-		}
-	}
-
-	INT32 convert24To32Bits(const UINT8* input)
-	{
-		bool isNegative = input[2] & 0x80;
-		if (isNegative) // Sign extend if negative
-			return (0xFF << 24) | (input[2] << 16) | (input[1] << 8) | input[0];
-		else
-			return (input[2] << 16) | (input[1] << 8) | input[0];
-	}
-
-	void convert32To24Bits(INT32 input, UINT8* output)
-	{
-		UINT32 valToEncode = *(UINT32*)&input;
-		output[0] = valToEncode & 0x000000FF;
-		output[1] = (valToEncode >> 8) & 0x000000FF;
-		output[2] = (valToEncode >> 16) & 0x000000FF;
-	}
-
-	void convertToMono24(UINT8* input, UINT8* output, UINT32 numSamples, UINT32 numChannels)
-	{
-		for (UINT32 i = 0; i < numSamples; i++)
-		{
-			INT32 sum = 0;
-			for (UINT32 j = 0; j < numChannels; j++)
-			{
-				sum += convert24To32Bits(input);
-				input += 3;
-			}
-
-			INT32 avg = sum / numChannels;
-			convert32To24Bits(avg, output);
-			output += 3;
-		}
-	}
-
-	void convertToMono32(INT32* input, INT32* output, UINT32 numSamples, UINT32 numChannels)
-	{
-		for (UINT32 i = 0; i < numSamples; i++)
-		{
-			INT64 sum = 0;
-			for (UINT32 j = 0; j < numChannels; j++)
-			{
-				sum += *input;
-				++input;
-			}
-
-			*output = sum / numChannels;
-			++output;
-		}
-	}
-
-	void convert8To32Bits(UINT8* input, INT32* output, UINT32 numSamples)
-	{
-		for(UINT32 i = 0; i < numSamples; i++)
-		{
-			INT8 val = (INT8)(input[i] - 128);
-			output[i] = val << 24;
-		}
-	}
-
-	void convert16To32Bits(INT16* input, INT32* output, UINT32 numSamples)
-	{
-		for (UINT32 i = 0; i < numSamples; i++)
-			output[i] = input[i] << 16;
-	}
-
-	void convert24To32Bits(UINT8* input, INT32* output, UINT32 numSamples)
-	{
-		for (UINT32 i = 0; i < numSamples; i++)
-		{
-			output[i] = convert24To32Bits(input);
-			input += 3;
-		}
-	}
-
-	void convert32To8Bits(INT32* input, UINT8* output, UINT32 numSamples)
-	{
-		for (UINT32 i = 0; i < numSamples; i++)
-		{
-			INT8 val = (INT8)(input[i] >> 24);
-			output[i] = (UINT8)(val + 128);
-		}
-	}
-
-	void convert32To16Bits(INT32* input, INT16* output, UINT32 numSamples)
-	{
-		for (UINT32 i = 0; i < numSamples; i++)
-			output[i] = (INT16)(input[i] >> 16);
-	}
-
-	void convert32To24Bits(INT32* input, UINT8* output, UINT32 numSamples)
-	{
-		for (UINT32 i = 0; i < numSamples; i++)
-		{
-			convert32To24Bits(input[i], output);
-			output += 3;
-		}
-	}
-
-	void convertBitDepth(UINT8* input, UINT32 inBitDepth, UINT8* output, UINT32 outBitDepth, UINT32 numSamples)
-	{
-		INT32* srcBuffer = nullptr;
-
-		bool needTempBuffer = inBitDepth != 32;
-		if (needTempBuffer)
-			srcBuffer = (INT32*)bs_stack_alloc(numSamples * sizeof(INT32));
-		else
-			srcBuffer = (INT32*)input;
-
-		// Note: I convert to a temporary 32-bit buffer and then use that to convert to actual requested bit depth. 
-		//       It would be more efficient to convert directly from source to requested depth without a temporary buffer,
-		//       at the cost of additional complexity. If this method ever becomes a performance issue consider that.
-		switch(inBitDepth)
-		{
-		case 8:
-			convert8To32Bits(input, srcBuffer, numSamples);
-			break;
-		case 16:
-			convert16To32Bits((INT16*)input, srcBuffer, numSamples);
-			break;
-		case 24:
-			convert8To32Bits(input, srcBuffer, numSamples);
-			break;
-		case 32:
-			// Do nothing
-			break;
-		default:
-			assert(false);
-			break;
-		}
-
-		switch(outBitDepth)
-		{
-		case 8:
-			convert32To8Bits(srcBuffer, output, numSamples);
-			break;
-		case 16:
-			convert32To16Bits(srcBuffer, (INT16*)output, numSamples);
-			break;
-		case 24:
-			convert32To24Bits(srcBuffer, output, numSamples);
-			break;
-		case 32:
-			memcpy(output, srcBuffer, numSamples * sizeof(INT32));
-			break;
-		default:
-			assert(false);
-			break;
-		}
-
-		if (needTempBuffer)
-		{
-			bs_stack_free(srcBuffer);
-			srcBuffer = nullptr;
-		}
-	}
-
 	OAImporter::OAImporter()
 		:SpecificImporter()
 	{
@@ -263,28 +76,7 @@ namespace BansheeEngine
 			UINT32 monoBufferSize = numSamplesPerChannel * info.bitDepth;
 			UINT8* monoBuffer = (UINT8*)bs_alloc(monoBufferSize);
 
-			for(UINT32 i = 0; i < numSamplesPerChannel; i++)
-			{
-				switch(info.bitDepth)
-				{
-				case 8:
-					convertToMono8(sampleBuffer, monoBuffer, numSamplesPerChannel, info.numChannels);
-					break;
-				case 16:
-					convertToMono16((INT16*)sampleBuffer, (INT16*)monoBuffer, numSamplesPerChannel, info.numChannels);
-					break;
-				case 24:
-					convertToMono24(sampleBuffer, monoBuffer, numSamplesPerChannel, info.numChannels);
-					break;
-				case 32:
-					convertToMono32((INT32*)sampleBuffer, (INT32*)monoBuffer, numSamplesPerChannel, info.numChannels);
-					break;
-				default:
-					assert(false);
-					break;
-				}
-
-			}
+			AudioUtility::convertToMono(sampleBuffer, monoBuffer, info.bitDepth, numSamplesPerChannel, info.numChannels);
 
 			info.numSamples = numSamplesPerChannel;
 			info.numChannels = 1;
@@ -301,7 +93,7 @@ namespace BansheeEngine
 			UINT32 outBufferSize = info.numSamples * (clipIO->getBitDepth() / 8);
 			UINT8* outBuffer = (UINT8*)bs_alloc(outBufferSize);
 
-			convertBitDepth(sampleBuffer, info.bitDepth, outBuffer, clipIO->getBitDepth(), info.numSamples);
+			AudioUtility::convertBitDepth(sampleBuffer, info.bitDepth, outBuffer, clipIO->getBitDepth(), info.numSamples);
 
 			info.bitDepth = clipIO->getBitDepth();