//
// Asura_Platform_OpenAL.cpp
//
// Created by Andy Patrick - 20-09-2007
// 
// Copyright (C) 2007 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"

#include "Sound/Asura_OpenAL.h"
#if defined( ASURA_USE_OPENAL ) && ( ASURA_USE_OPENAL == 1 ) && !defined(ASURA_USE_AUDIO_SYSTEM)
#include "Sound/Asura_PC_Sound.h"

// Forward definitions
static ALenum GetOpenALFormat( const WAVEFORMATEX* pxWfx );

/* ------------------------------------------------------------------------- */

Asura_OpenAL_Sound_API& Asura_OpenAL_Sound_API::Platform_GetAPI()
{
	return Asura_PC_Sound::GetAPI();
}

/* ------------------------------------------------------------------------- */

void Asura_OpenAL_Sound_API::Platform_Initialise()
{

}

/* ------------------------------------------------------------------------- */

// JAT 18/10/07 - let the h/w platform specify this value
int Asura_OpenAL_Sound_API::Platform_GetNumAuxSendsPerSource( void ) 
{
	int iAuxSendsPerSource = 0;
	// Get the actual number of auxiliary sends available
	alcGetIntegerv( m_pxDevice, ALC_MAX_AUXILIARY_SENDS, 1, &iAuxSendsPerSource );
	#ifdef ASURA_ASSERT
		ALenum xError = alGetError();
	#endif
	Asura_Assertf( xError == AL_NO_ERROR, ( "Couldn't get max auxiliary sends, xError 0x%X", xError ) );

	return iAuxSendsPerSource;
}

/* ------------------------------------------------------------------------- */

bool Asura_OpenAL_ActiveSound_API::Platform_FillBuffer( ALuint m_uBufferID, const void* pvFormat, const u_char* pucData, u_int uSize )
{
	ALenum xError = alGetError();
	const WAVEFORMATEX* pxWfx = reinterpret_cast<const WAVEFORMATEX*>( pvFormat );
	ALenum xFormat = GetOpenALFormat( pxWfx );

	if ( xFormat == AL_INVALID )
	{
		return false;
	}

	alBufferData( m_uBufferID, xFormat, pucData, uSize, pxWfx->nSamplesPerSec );

	if ( ( xError = alGetError() ) != AL_NO_ERROR )
	{
		Asura_Assertf( xError == AL_NO_ERROR, ( "Failed to buffer data, error %x", xError ) );
		return false;
	}

	return true;
}

/* ------------------------------------------------------------------------- */

static ALenum GetOpenALFormat( const WAVEFORMATEX* pxWfx )
{
	ALenum xFormat = AL_INVALID;

	// Work out what the format "should" be, then call alGetEnumValue, which
	// will fail if the desired wave format is not supported by the hardware.
	// (This code lifted from the OpenAL "Framework" sample. However, the 
	// sample also checked "format tag" and "channel mask" but we don't seem 
	// to have access to that and it didn't seem to make much difference anyway?)

	if ( pxWfx->nChannels == 1 )
	{
		xFormat = pxWfx->wBitsPerSample == 16 ? alGetEnumValue( "AL_FORMAT_MONO16" ) : alGetEnumValue( "AL_FORMAT_MONO8" );
	}
	else if ( pxWfx->nChannels == 2 )
	{
		xFormat = pxWfx->wBitsPerSample == 16 ? alGetEnumValue( "AL_FORMAT_STEREO16" ) : alGetEnumValue( "AL_FORMAT_STEREO8" );
	}
	else if ( ( pxWfx->nChannels == 4 ) && ( pxWfx->wBitsPerSample == 16 ) )
	{
		xFormat = alGetEnumValue("AL_FORMAT_QUAD16" );
	}
	else if ( ( pxWfx->nChannels == 6 ) && ( pxWfx->wBitsPerSample == 16 ) )
	{
		xFormat = alGetEnumValue("AL_FORMAT_51CHN16" );
	}
	else if ( ( pxWfx->nChannels == 7 ) && ( pxWfx->wBitsPerSample == 16 ) )
	{
		xFormat = alGetEnumValue("AL_FORMAT_61CHN16" );
	}
	else if ( ( pxWfx->nChannels == 8 ) && ( pxWfx->wBitsPerSample == 16 ) )
	{
		xFormat = alGetEnumValue("AL_FORMAT_71CHN16" );
	}

	Asura_Assertf( xFormat != AL_INVALID, ( "Wave format not supported (%d channels, %d bits per sample)", pxWfx->nChannels, pxWfx->wBitsPerSample ) );

	return xFormat;
}

/* ------------------------------------------------------------------------- */

#endif	//defined( ASURA_USE_OPENAL ) && ( ASURA_USE_OPENAL == 1 ) && !defined(ASURA_USE_AUDIO_SYSTEM)
