#include "Mix/Private/Sound/EmitterMediator.h"

#include "Mix/ScopedLock.h"
#include "Mix/Private/Sound/Manager.h"

namespace Mix{ namespace Sound{

////////////////////////////////////////////////////////////////////////////////////////////////////
// EmitterMediator
// カレントスレッドから飛び出されるメソッド
////////////////////////////////////////////////////////////////////////////////////////////////////

EmitterMediator* EmitterMediator::CreateInstance(	Mix::Sound::PX3DAudioCalculate pCalcFunc,
													const X3DAUDIO_HANDLE& handle,
													UInt32 masterChannels,
													UInt32 channels )
{
	return MIX_LIB_NEW_T( Mix::Memory::SECTION_SOUND, EmitterMediator, pCalcFunc, handle, masterChannels, channels );
}

EmitterMediator::EmitterMediator(	Mix::Sound::PX3DAudioCalculate pCalcFunc,
									const X3DAUDIO_HANDLE& handle,
									UInt32 masterChannels,
									UInt32 channels ) :
									m_pCalcFunc( NULL )
{
	MIX_ASSERT( pCalcFunc != NULL );

	m_pCalcFunc = pCalcFunc;

	Mix::Memory::Copy( &m_Handle, &handle, sizeof( X3DAUDIO_HANDLE ) );

	m_Matrix.resize( ( masterChannels * channels ), 0.0f );

	m_DSPSettings.pMatrixCoefficients = &( m_Matrix[0] );
	m_DSPSettings.SrcChannelCount = channels;
	m_DSPSettings.DstChannelCount = masterChannels;
	m_DSPSettings.pDelayTimes = NULL;
	m_DSPSettings.LPFDirectCoefficient = 0.0f;
	m_DSPSettings.LPFReverbCoefficient = 0.0f;
	m_DSPSettings.ReverbLevel = 0.0f;
	m_DSPSettings.DopplerFactor = 1.0f;
	m_DSPSettings.EmitterToListenerAngle = 0.0f;
	m_DSPSettings.EmitterToListenerDistance = 0.0f;
	m_DSPSettings.EmitterVelocityComponent = 1.0f;
	m_DSPSettings.ListenerVelocityComponent = 1.0f;
}

EmitterMediator::~EmitterMediator( void )
{
}

void EmitterMediator::UpdateDSPSettings( const X3DAUDIO_LISTENER& lp, const X3DAUDIO_EMITTER& ep )
{
	Mix::ScopedLock lock( m_Sync );
	m_pCalcFunc( m_Handle, &lp, &ep, X3DAUDIO_CALCULATE_MATRIX | X3DAUDIO_CALCULATE_DOPPLER, &m_DSPSettings );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// EmitterMediator
// サウンドスレッドから呼び出されるメソッド
////////////////////////////////////////////////////////////////////////////////////////////////////

void EmitterMediator::ApplyDSPSettings( IXAudio2SourceVoice* pVoice )
{
	m_Sync.Enter();

	pVoice->SetOutputMatrix(	NULL,
								m_DSPSettings.SrcChannelCount,
								m_DSPSettings.DstChannelCount,
								m_DSPSettings.pMatrixCoefficients );

	pVoice->SetFrequencyRatio( m_DSPSettings.DopplerFactor );

	m_Sync.Leave();
}

}}
