/*=============================================================================
	CASampleTools.h

	$Log: CASampleTools.h,v $
	Revision 1.8  2003/04/25 02:39:26  ealdrich
	more tweaking for Windows
	
	Revision 1.7  2003/04/09 02:25:48  ealdrich
	Fix types on Windows.
	
	Revision 1.6  2002/06/06 00:37:40  ealdrich
	Fix Int64SwapEndian on Windows
	
	Revision 1.5  2002/06/01 00:46:25  ealdrich
	fix windows build -- Windows doesn't like 'long long'
	
	Revision 1.4  2002/05/14 00:18:12  luke
	integrate changes made in SoundMgr respository <ealdrich, luke>
	
	Revision 1.3  2002/04/25 22:26:28  jcm10
	define the constants in the .cpp and define the types if we have to
	
	Revision 1.2  2002/04/05 23:12:51  jcm10
	rewrite everything in terms of Doug's new code
	
	Revision 1.1  2002/03/01 01:52:40  jcm10
	moved here from ../Utility
	
	Revision 1.9  2002/02/02 00:37:16  dwyatt
	fix for gcc3
	
	Revision 1.8  2002/01/17 01:36:40  jcm10
	use TARGET_RT_BIG_ENDIAN
	
	Revision 1.7  2001/11/21 23:29:00  jcm10
	add 32 & 64 bit endian swapping routines and routines for signed vs unsigned
	
	Revision 1.6  2001/04/05 01:31:57  jcm10
	add endian swapping routines to eliminate dependancy on CoreServices
	
	Revision 1.5  2001/01/08 23:51:04  jcm10
	remove #pragma once, since gcc claims it to be obsolete and issues an annoying warning to that effect when all warnings are enabled
	
	Revision 1.4  2000/12/16 01:50:36  jcm10
	add a sanity checking funciton
	
	Revision 1.3  2000/10/02 18:34:29  jcm10
	XFiles work better
	
	Revision 1.2  2000/09/22 19:35:53  jcm10
	more XFiles stuff
	
	Revision 1.1  2000/09/21 19:45:24  jcm10
	first checked in
	
	Revision 0.0  2000/01/01 12:34:56  jcm10
	created
		
	$NoKeywords: $
=============================================================================*/
#if !defined(__CASampleTools_h__)
#define __CASampleTools_h__

//=============================================================================
//	Includes
//=============================================================================

#include "CAConditionalMacros.h"

#if TARGET_API_MAC_OSX
	#include <sys/types.h>
#else
	#include <MacTypes.h>
	#include "CFBase.h"
	typedef unsigned char		u_int8_t;
	
	typedef unsigned short		u_int16_t;
	
	typedef unsigned long		u_int32_t;
	
#if TYPE_LONGLONG
#if TARGET_OS_WIN32
	typedef SInt64				int64_t;
	typedef UInt64				u_int64_t;
#else
	typedef long long			int64_t;
	typedef unsigned long long	u_int64_t;
#endif
#endif
#endif

//=============================================================================
//	CASampleTools
//
//	This class contains routines for converting between
//	various linear PCM sample formats.
//=============================================================================

class	CASampleTools
{

//	Sample Value Constants
public:
	static const int8_t		sMaxSInt8Sample;
	static const int8_t		sMinSInt8Sample;
	static const float		sHalfRangeSInt8Sample;
	static const int16_t	sMaxSInt16Sample;
	static const int16_t	sMinSInt16Sample;
	static const float		sHalfRangeSInt16Sample ;//= 32768.0;
	static const float		sMaxSInt8Float32Sample ;//= static_cast<float>(sMaxSInt8Sample) / sHalfRangeSInt8Sample;
	static const float		sMinSInt8Float32Sample ;//= static_cast<float>(sMinSInt8Sample) / sHalfRangeSInt8Sample;
	static const float		sMaxSInt16Float32Sample ;//= static_cast<float>(sMaxSInt16Sample) / sHalfRangeSInt16Sample;
	static const float		sMinSInt16Float32Sample ;//= static_cast<float>(sMinSInt16Sample) / sHalfRangeSInt16Sample;

//	Endian Swapping Routines
public:
	static u_int16_t		Int16SwapEndian(u_int16_t inValue)
	{
		return ((inValue << 8) & 0xFF00) | ((inValue >> 8) & 0x00FF);
	}

	static u_int32_t		Int32SwapEndian(u_int32_t inValue)
	{
		return ((inValue << 24) & 0xFF000000UL) | ((inValue << 8) & 0x00FF0000UL) | ((inValue >> 8) & 0x0000FF00UL) | ((inValue >> 24) & 0x000000FFUL);
	}

#if TARGET_OS_WIN32
	/* the inline macros crash MSDEV's optimizer on Windows. */
	static u_int64_t			Int64SwapEndian(UInt64 inValue)
	{
		u_int64_t temp;
		((UnsignedWide*)&temp)->lo = Int32SwapEndian(((UnsignedWide*)&inValue)->hi);
		((UnsignedWide*)&temp)->hi = Int32SwapEndian(((UnsignedWide*)&inValue)->lo);
		return temp;
	}
#else
	static u_int64_t		Int64SwapEndian(u_int64_t inValue)
	{
		return ((inValue << 56) & 0xFF00000000000000ULL) | ((inValue << 40) & 0x00FF000000000000ULL) | ((inValue << 24) & 0x0000FF0000000000ULL) | ((inValue << 8) & 0x000000FF00000000ULL) | ((inValue >> 8) & 0x00000000FF000000ULL) | ((inValue >> 24) & 0x0000000000FF0000ULL) | ((inValue >> 40) & 0x000000000000FF00ULL) | ((inValue >> 56) & 0x00000000000000FFULL);
	}
#endif	
#if	__ppc__

	static int16_t			SInt16BigToNativeEndian(int16_t inValue) { return inValue; }
	static int16_t			SInt16NativeToBigEndian(int16_t inValue) { return inValue; }

	static int16_t			SInt16LittleToNativeEndian(int16_t inValue) { return Int16SwapEndian(inValue); }
	static int16_t			SInt16NativeToLittleEndian(int16_t inValue) { return Int16SwapEndian(inValue); }

	static u_int16_t		UInt16BigToNativeEndian(u_int16_t inValue) { return inValue; }
	static u_int16_t		UInt16NativeToBigEndian(u_int16_t inValue) { return inValue; }

	static u_int16_t		UInt16LittleToNativeEndian(u_int16_t inValue) { return Int16SwapEndian(inValue); }
	static u_int16_t		UInt16NativeToLittleEndian(u_int16_t inValue) { return Int16SwapEndian(inValue); }

	static int32_t			SInt32BigToNativeEndian(int32_t inValue) { return inValue; }
	static int32_t			SInt32NativeToBigEndian(int32_t inValue) { return inValue; }

	static int32_t			SInt32LittleToNativeEndian(int32_t inValue) { return Int32SwapEndian(inValue); }
	static int32_t			SInt32NativeToLittleEndian(int32_t inValue) { return Int32SwapEndian(inValue); }

	static u_int32_t		UInt32BigToNativeEndian(u_int32_t inValue) { return inValue; }
	static u_int32_t		UInt32NativeToBigEndian(u_int32_t inValue) { return inValue; }

	static u_int32_t		UInt32LittleToNativeEndian(u_int32_t inValue) { return Int32SwapEndian(inValue); }
	static u_int32_t		UInt32NativeToLittleEndian(u_int32_t inValue) { return Int32SwapEndian(inValue); }

	static int64_t			SInt64BigToNativeEndian(int64_t inValue) { return inValue; }
	static int64_t			SInt64NativeToBigEndian(int64_t inValue) { return inValue; }

	static int64_t			SInt64LittleToNativeEndian(int64_t inValue) { return Int64SwapEndian(inValue); }
	static int64_t			SInt64NativeToLittleEndian(int64_t inValue) { return Int64SwapEndian(inValue); }

	static u_int64_t		UInt64BigToNativeEndian(u_int64_t inValue) { return inValue; }
	static u_int64_t		UInt64NativeToBigEndian(u_int64_t inValue) { return inValue; }

	static u_int64_t		UInt64LittleToNativeEndian(u_int64_t inValue) { return Int64SwapEndian(inValue); }
	static u_int64_t		UInt64NativeToLittleEndian(u_int64_t inValue) { return Int64SwapEndian(inValue); }

#else

	static int16_t			SInt16BigToNativeEndian(int16_t inValue) { return Int16SwapEndian(inValue); }
	static int16_t			SInt16NativeToBigEndian(int16_t inValue) { return Int16SwapEndian(inValue); }

	static int16_t			SInt16LittleToNativeEndian(int16_t inValue) { return inValue; }
	static int16_t			SInt16NativeToLittleEndian(int16_t inValue) { return inValue; }

	static u_int16_t		UInt16BigToNativeEndian(u_int16_t inValue) { return Int16SwapEndian(inValue); }
	static u_int16_t		UInt16NativeToBigEndian(u_int16_t inValue) { return Int16SwapEndian(inValue); }

	static u_int16_t		UInt16LittleToNativeEndian(u_int16_t inValue) { return inValue; }
	static u_int16_t		UInt16NativeToLittleEndian(u_int16_t inValue) { return inValue; }

	static int32_t			SInt32BigToNativeEndian(int32_t inValue) { return Int32SwapEndian(inValue); }
	static int32_t			SInt32NativeToBigEndian(int32_t inValue) { return Int32SwapEndian(inValue); }

	static int32_t			SInt32LittleToNativeEndian(int32_t inValue) { return inValue; }
	static int32_t			SInt32NativeToLittleEndian(int32_t inValue) { return inValue; }

	static u_int32_t		UInt32BigToNativeEndian(u_int32_t inValue) { return Int32SwapEndian(inValue); }
	static u_int32_t		UInt32NativeToBigEndian(u_int32_t inValue) { return Int32SwapEndian(inValue); }

	static u_int32_t		UInt32LittleToNativeEndian(u_int32_t inValue) { return inValue; }
	static u_int32_t		UInt32NativeToLittleEndian(u_int32_t inValue) { return inValue; }

	static int64_t			SInt64BigToNativeEndian(int64_t inValue) { return Int64SwapEndian(inValue); }
	static int64_t			SInt64NativeToBigEndian(int64_t inValue) { return Int64SwapEndian(inValue); }

	static int64_t			SInt64LittleToNativeEndian(int64_t inValue) { return inValue; }
	static int64_t			SInt64NativeToLittleEndian(int64_t inValue) { return inValue; }

	static u_int64_t		UInt64BigToNativeEndian(u_int64_t inValue) { return Int64SwapEndian(inValue); }
	static u_int64_t		UInt64NativeToBigEndian(u_int64_t inValue) { return Int64SwapEndian(inValue); }

	static u_int64_t		UInt64LittleToNativeEndian(u_int64_t inValue) { return inValue; }
	static u_int64_t		UInt64NativeToLittleEndian(u_int64_t inValue) { return inValue; }

#endif

//	Copy Routines
public:
	//	signed 8 bit integer to native endian 32 bit float
	static void				CopySInt8ToFloat32Samples(const int8_t* inSource, float* outDestination, u_int32_t inNumberSamples);

	//	signed little endian 16 bit integer to native endian 32 bit float
	static void				CopyLESInt16ToFloat32Samples(const int16_t* inSource, float* outDestination, u_int32_t inNumberSamples);

	//	signed big endian 16 bit integer to native endian 32 bit float
	static void				CopyBESInt16ToFloat32Samples(const int16_t* inSource, float* outDestination, u_int32_t inNumberSamples);
	
	//	signed little endian 32 bit integer to native endian 32 bit float
	static void				CopyLESInt32ToFloat32Samples(const int32_t* inSource, float* outDestination, u_int32_t inNumberSamples);

	//	signed big endian 32 bit integer to native endian 32 bit float
	static void				CopyBESInt32ToFloat32Samples(const int32_t* inSource, float* outDestination, u_int32_t inNumberSamples);
	
	//	native endian 32 bit float to signed 8 bit integer
	static void				CopyFloat32ToSInt8Samples(const float* inSource, int8_t* outDestination, u_int32_t inNumberSamples);

	//	native endian 32 bit float to signed little endian 16 bit integer
	static void				CopyFloat32ToLESInt16Samples(const float* inSource, int16_t* outDestination, u_int32_t inNumberSamples);

	//	native endian 32 bit float to signed big endian 16 bit integer
	static void				CopyFloat32ToBESInt16Samples(const float* inSource, int16_t* outDestination, u_int32_t inNumberSamples);

	//	native endian 32 bit float to signed little endian 32 bit integer
	static void				CopyFloat32ToLESInt32Samples(const float* inSource, int32_t* outDestination, u_int32_t inNumberSamples);

	//	native endian 32 bit float to signed big endian 32 bit integer
	static void				CopyFloat32ToBESInt32Samples(const float* inSource, int32_t* outDestination, u_int32_t inNumberSamples);

	//	mix two native endian 32 bit float buffers
	static void				MixFloat32Samples(const float* inSource, float* outDestination, u_int32_t inNumberSamples);

};

#endif
