/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2008.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: include/sgx/audio/soundengine.hpp

*/

#ifndef SGX_AUDIO_SOUND_ENGINE_HPP
#define SGX_AUDIO_SOUND_ENGINE_HPP	1

#define AUDIO_DEFAULT_NORMALIZATION_GROUPS	16
#define AUDIO_DEFAULT_LOGICAL_CHANNELS	256

class CSampleData;
class CLogicalChannel;
class CMixChannel;
class CMixOutput;


class CSoundListener 
{
public:
	sgxVector3 vPos;
	sgxVector3 vOrientation;
	sgxVector3 vPosNormal;
	sgxVector3 vOrientationNormal;

	CSoundListener() {
		vPos.zero();
		vPosNormal.zero();
		vOrientation.set(sgxVector3::UnitY);
		vOrientationNormal.set(sgxVector3::UnitY);
	}
};

class CSGXAudioEngine : public CSGXEngine
{
public:
	typedef enum {
		eDefault,
		eInMemory,
		eDiscStream,
		eSequenced,
	} ResourceContext;

	static CSGXAudioEngine *get();
	static CSGXAudioEngine *create();
	virtual void initialize();
	virtual void prepareNormalizationGroups(tUINT32 numGroups);
	virtual void prepareLogicalChannels(tUINT32 numChannels);
	virtual void update(const tREAL32 time_elapsed);
	virtual void release();

	// User methods
	virtual CSampleData *		createSample(const sgxString &filename, const CSGXAudioEngine::ResourceContext context=eDefault);
	virtual CSampleData *		registerScenarioSound(const sgxString &filename, const CSGXAudioEngine::ResourceContext context=eDefault);
	virtual CSampleData *		registerGlobalSound(const sgxString &filename, const CSGXAudioEngine::ResourceContext context=eDefault);
	virtual void				unregisterObjects();

	virtual CLogicalChannel *	playSound(CSampleData *pSound, CLogicalChannel *pChannel=NULL, CMixChannel *pInitialMix=NULL);
	virtual CLogicalChannel *	playSoundAt(CSampleData *pSound, const sgxVector3 &pos, CLogicalChannel *pChannel=NULL, CMixChannel *pInitialMix=NULL);
	virtual tBOOL				stopSound(CLogicalChannel *pLogical);
	virtual tBOOL				stopAllSounds(CSampleData *pSound);

	virtual CLogicalChannel *	getFreeChannel() const;
	virtual CLogicalChannel *	getDisposableChannel() const;


	// Control methods
	virtual void setListenerPosition(const sgxVector3 &pos);
	virtual void setListenerOrientation(const sgxVector3 &dir);

	//
	virtual tUINT32	getMaxChannels() const;

	virtual void setMute(tBOOL muted);
	virtual tBOOL getMute() const;
	virtual void suspendEngine();
	virtual void resumeEngine();

	virtual void evaluateMixerChain(CMixOutput *pChannel, CLogicalChannel *pLogical, const tREAL32 time_elapsed);

protected:
	CSGXAudioEngine();


	virtual void processGameplayMixer(CMixOutput *pChannel, CLogicalChannel *pLogical, const tREAL32 time_elapsed);
	virtual void processTechnologyMixer(CMixOutput *pChannel, const CLogicalChannel *pLogical, const tREAL32 time_elapsed);
	virtual void processUserMixer(CMixOutput *pChannel, const CLogicalChannel *pLogical, const tREAL32 time_elapsed);
	virtual void updateHardwareMixer(tREAL32 time_elapsed);

	virtual void processGameplayLogicalMixer(CMixOutput *pChannel, const CLogicalChannel *pLogical, const tREAL32 time_elapsed);
	virtual void processGameplayControlMixer(CMixOutput *pChannel, CLogicalChannel *pLogical, const tREAL32 time_elapsed);

	static CSGXAudioEngine *m_pSingleton;

	CSoundListener		m_Listener;
	tBOOL				m_bMute;

	tUINT32				m_NumChannels;
	tUINT32				m_VolumeTable[1024];
	CMixChannel **		m_pMixChannels;
	CMixOutput **		m_MixOutput;
	CLogicalChannel **	m_pChannels;

	tUINT32				m_NumNormalizationGroups;
	tREAL32	*			m_pNormalization;	
};

#endif /* SGX_AUDIO_SOUND_ENGINE_HPP */
