/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
////																					 ////
////																					 ////
////								   - HUtil.cpp -    								 ////
////																					 ////
////																					 ////
////				Implémentation des fonctions SCOL de la librairie sonore			 ////
////									 Version  1.0									 ////
////																					 ////
////								  Hilaire Verschuere								 ////
////																					 ////
////																					 ////
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////

#ifndef _HUTIL_H_
#define _HUTIL_H_

#define DEFINE_HGUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
	EXTERN_C const GUID name = { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } }

#include "dsound.h"
#include <mmreg.h>
#include <stdio.h>
#include <math.h>
#include "../SCOL/winuser.h"
#include "../SCOL/macro.h"
#include "mpglib.h"
#include <list>
using namespace std ;




//-----------------------------------------------------------------------------
// constants
//-----------------------------------------------------------------------------
const int DS_PRIMARY_MONO		 =     1 ;	// number of channels for primary Direct Sound Buffer
const int DS_PRIMARY_STEREO		 =     2 ;  // number of channels for primary Direct Sound Buffer
const int DS_PRIMARY_8BITS		 =     8 ;  // SampleRate of 8 bits for primary Direct Sound Buffer
const int DS_PRIMARY_16BITS		 =	  16 ;  // SampleRate of 16 bits for primary Direct Sound Buffer
const int DS_PRIMARY_FREQ		 = 44100 ;  // Number of sample by seconde for primary Direct Sound Buffer
const int INIT_VOLUME			 =    75 ;  // initial volume for each AsSnd
const int INIT_VOLUME_GLOBAL	 =   100 ;  // initial global volume for application
const int INIT_VOLUME_CONE		 =     0 ;  // initial volume out of cone for 3d sound
const int INIT_PAN				 =     0 ;  // initial panoramique for each AsSnd
const int NB_PLAY_NOTIFICATIONS  =     8 ;  // Number of notification points in the buffer used in streaming
const int NB_REC_NOTIFICATIONS   =	   8 ;  // Number of notification points in the buffer used in recording


// Flags used to create Direct Sound Buffer
#define   DSBCAPS_CTRL ( DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 )
#define	  DSBCAPS_3D   ( DSBCAPS_CTRL3D | DSBCAPS_MUTE3DATMAXDISTANCE )

// Constants used in SCOL
const int AS_SND_STATIC			=   0 ;
const int AS_SND_STREAMING		=   1 ;
const int AS_SND_LINEAR			=   1 ;
const int AS_SND_CIRCULAR		=   2 ;
const int AS_SND_END_REFLEX		=  -1 ;
const int AS_SND_LINKED_TO_H3D	=   1 ;
const int AS_SND_LOOP			=   1 ;
const int AS_WAVE_LOOP			=   1 ;



// MP3 constants
static char	VBRTag[]			 =      {"Xing"} ;
//const int   TITLEBUFLEN			 = (MAX_PATH-10) ;
const int   VBRHEADERSIZE		 =			120 ;
const int   FBSIZE				 =		   2048 ;
const int   OBSIZE				 =		   4608 ;
const int   FRAMES_FLAG			 =		 0x0001 ;
const int   BYTES_FLAG			 =		 0x0002 ;
const int   TOC_FLAG			 =		 0x0004 ;
const int   VBR_SCALE_FLAG		 =		 0x0008 ;
#define     FRAMES_AND_BYTES (FRAMES_FLAG | BYTES_FLAG)




//-----------------------------------------------------------------------------
// reflex
//-----------------------------------------------------------------------------
#define NB_RFL_ASSND		2
#define RFL_EVT_ASSND		0
#define RFL_NEXT_ASSND		1
#define NB_RFL_ASRECORDER	1
#define RFL_ASRECORDER		0


// old Easy Sound API
enum { RFL_RECOPEN, RFL_RECCLOSE, RFL_RECBUF, NB_RFL_SOUNDREC } ;
enum { RFL_PLAYOPEN, RFL_PLAYCLOSE, RFL_PLAYBUF, NB_RFL_SOUNDPLAY } ;


//-----------------------------------------------------------------------------
// Miscellaneous helper functions
//-----------------------------------------------------------------------------
#define SAFE_DELETE(p)        { if(p) { delete (p);     (p)=NULL; } }
#define SAFE_DELETE_ARRAY(p)  { if(p) { delete[] (p);   (p)=NULL; } }
#define SAFE_RELEASE(p)       { if(p) { (p)->Release(); (p)=NULL; } }
#define SAFE_CLOSE_HANDLE(p)  { if(p) { CloseHandle(p); (p)=NULL; } }
#define SAFE_DELETE_BUFFER(p) { if(p) { if( (p)->buffer ) delete[] (p)->buffer; delete (p); (p)=NULL; } }

#ifdef FAILED 
	#undef FAILED
	#define FAILED(hr) hr
#endif

#ifdef S_OK
	#undef S_OK
	#define S_OK 0
#endif

#ifdef S_FALSE
	#undef S_FALSE
	#define S_FALSE 1
#endif



// Conversion d'un échantillon : taille en octets -> durée en millisecondes
inline long CharToMs( WAVEFORMATEX* pwfx, long size ) 
{
	if( !pwfx ) return -1 ;

	long time = 1000 * ( size / pwfx->nAvgBytesPerSec ) ;

	time += (long)( (double)( (size % pwfx->nAvgBytesPerSec) * 1000 ) / (double)pwfx->nAvgBytesPerSec ) ;

	return time ;
}


// Conversion d'un échantillon : durée en millisecondes -> taille en octets
inline long MsToChar( WAVEFORMATEX* pwfx, long time )
{
	if( !pwfx ) return -1 ;

	long size = pwfx->nAvgBytesPerSec * (time / 1000) ;

	size += (long)( (double)( (time % 1000) * pwfx->nAvgBytesPerSec ) / (double)1000 ) ;
	size -= ( size % pwfx->nBlockAlign ) ;

	return size ;
}


// buffer copy
inline void _memcpy( char* dest, char* src, int tailleBuffer )
{
#ifdef _X86_
	if( src && ( tailleBuffer > 0 ) ) _asm
	{               
			pushad

			xor  eax, eax
			xor  edi, edi
			xor  esi, esi
			mov  ecx, tailleBuffer
			mov  esi, src
			mov  edi, dest
			
		bcle :
			mov  al, byte ptr [esi]
			mov  byte ptr [edi], al
			inc  esi
			inc  edi
			dec  ecx
			jne  bcle

			popad
	}
#else
	memcpy( dest, src, tailleBuffer ) ;
#endif

}


// filling buffer
inline void _FillMemory( char* dest, int tailleBuffer, unsigned char data )
{
#ifdef _X86_
	if( tailleBuffer > 0 )
	_asm
	{
		pushad

		xor  eax, eax
		xor  edi, edi
		mov  al,  data
		mov  edi, dest
		mov  ecx, tailleBuffer
		rep  stosb

		popad
	}

#else
	FillMemory( dest, tailleBuffer, data ) ;
#endif

}




//-----------------------------------------------------------------------------
// Debug printing support
//-----------------------------------------------------------------------------
inline int _errmsg(char* txt)
{ 
	MessageBox( NULL, txt, "ERREUR MESSAGE", MB_OK ) ; 
	return S_FALSE ; 
}


#if defined DEBUG  |  defined _DEBUG
#define	ERRMSG(txt)	_errmsg(txt)
#else
	#define	ERRMSG(txt)	S_FALSE
#endif



//-----------------------------------------------------------------------------
// Extern function
//-----------------------------------------------------------------------------
void DeleteNode(mmachine m, int hash_tab, ZNode *baseNode) ;
int	 DelObj(mmachine m, int hash_tab, int handle) ;



//-----------------------------------------------------------------------------
// Structure definition
//-----------------------------------------------------------------------------
// Used in HData, each struct looks like a sample of sound 
struct lbuffers 
{
	char*		 buffer ; // buffer of data
	unsigned int size ;   // size of the buffer
	unsigned int pos ;    // reading position in the buffer, pos belong [0 size]
	lbuffers*	 prev ;   // previous element in chained list
	lbuffers*	 next ;   // next element in chained list
} ;


// Struct of events
struct EvtStruct 
{
	long posInBuffer ;        // position in the buffer, belong [0 sizeOfBuffer]
	list<unsigned long> pos ; // each positions in the all data, (each element of this list) % sizeOfBuffer is equal to posInBuffer
	int endPosition ;		  // if this event tell it is the end of data, endPosition is an index in list pos, else it is equal to -1
	HANDLE event ;			  // event which is received by thread
} ;
	

// Structure d'informations sur la musique dans le fichier mp3
typedef struct id3tag {
	char tag[3];
	char title[30];
	char artist[30];
	char album[30];
	char year[4];
	char comment[30];
	unsigned char genre;
} id3tag ;


// Structure d'informations sur le fichier mp3
typedef struct mp3info {
	int nbytes ;
	int freq ;
	int nch ;
	int hpos ;
	int hasVbrtag ;
	int lsf ;
	int bitrate ;
	unsigned int length;
} mp3info ;


// Structure d'informations sur un fichier mp3 à bitrate variable
typedef struct VBRTAGDATA
{
  int		h_id;			/* from MPEG header, 0=MPEG2, 1=MPEG1 */
  int		samprate;		/* determined from MPEG header */
  int		flags;			/* from Vbr header data */
  int		frames;			/* total bit stream frames from Vbr header data */
  int		bytes;			/* total bit stream bytes from Vbr header data*/
  int		vbr_scale;		/* encoded vbr scale from Vbr header data*/
  unsigned char	toc[100];	/* may be NULL if toc not desired*/
} VBRTAGDATA ;





//-----------------------------------------------------------------------------
// Classes or types used by this header
//-----------------------------------------------------------------------------
class ZSound;
class ZScene ;
class HSoundManager;
class WSound ;
class HSound;
class HRecord;
class HListener;
class HWave;
class HMp3;
class HAudio;
class HThread;
class HSndNotify;
class HRecNotify;

typedef list<HSound*>		HSOUNDLIST ;
typedef vector<EvtStruct>	EVTVECT ;




//-----------------------------------------------------------------------------
// Name: class HSoundManager
// Desc: 
//-----------------------------------------------------------------------------
class HSoundManager
{
protected:
    LPDIRECTSOUND	m_pDS ;  // Primary Direct Sound Buffer
	bool			m_DS_OK ;// DirectSound loaded
	bool			enable ; // is sound enable or disable
	int				volume ; // global volume for application
	
public:
	HSOUNDLIST listHSound ; // list of HSound instance

protected:
	inline void	Enable() { enable = true ; } 
	inline void	Disable() { enable = false ; } 

public:
    HSoundManager();
    ~HSoundManager();

	HRESULT				 Create( HWND hWnd ) ; 
    inline LPDIRECTSOUND GetDirectSound() { return m_pDS ; }
	inline float		 GetGlobalVolume() { return volume ; }	// return global volume
	void				 SetGlobalVolume(int vol) ;				// setting global volume
	inline bool			 IsEnable() { return enable ; }			// is sound enable or disable
	void				 EnableSound() ;						// enable sound
	void				 DisableSound() ;						// disable sound
	void				 Set3dMode( ZScene* pZScene ) ;			// Set mode 3D enable or disable for each AsSnd 3D if Listener is in the same Scene		
	inline bool			 IsDS_OK() { return m_DS_OK ; }			// Check if DirectSound is loaded
} ;






//-----------------------------------------------------------------------------
// Name: class HThread
// Desc: Encapsulates thread, need to be inherited
//-----------------------------------------------------------------------------
class HThread
{
protected:
	HANDLE		Thread ;
	DWORD		ThreadID ;
	bool		ThreadIsRunning ;

public:
	HThread();
	virtual ~HThread();

	HRESULT		Start();	// Start the tread
	void		Stop();     // Stop the Thread
	inline bool	IsRunning() { return ThreadIsRunning ; }
	
	virtual	DWORD ThreadProc() = 0 ; // Procedure which is waiting for message
} ;





//-----------------------------------------------------------------------------
// Name: class HThread
// Desc: Encapsulates evenements which happend during playing sound
//-----------------------------------------------------------------------------
class HSndNotify : public HThread
{
protected:
	HSound*	pHSound ;	// HSound from which HSndNotify is constructed
	EVTVECT	Evts ;		// Vector of events ( if we have a streaming sound, the NB_PLAY_NOTIFICATIONS first elements are notification points for streaming )
	int		handler ;   // used to post a message to the lead thread to prevent that callback must be activated

protected:
	void	EvtHappened( int numEvt ) ;  // Filter events comming from reading the buffer 

public:
	HSndNotify( HSound* pHSound );
	~HSndNotify();
	
	DWORD	ThreadProc();										// Procedure which is waiting for message
	void	AddEvt( unsigned long pos, bool endStreaming ) ;	// Add a struct EvtStruct to the vector of Events
	void	AddEndEvt() ;										// Add an end event, callback will be activated at the end of data
	void	RemoveEvt() ;										// Remove all event ( excepted streaming notification events and the end streaming event )
	HRESULT	SetNotify() ;										// Apply events to the Sound Buffer
	void    SetEndStreaming( unsigned long position ) ;			// Change the position of the end of data to stop streaming ( when datas are added )
	inline void SetHandler( int handler ) { this->handler = handler ; }
	
} ;




//-----------------------------------------------------------------------------
// Name: class HThread
// Desc: Encapsulates evenements which happend during playing sound
//-----------------------------------------------------------------------------
class HRecNotify : public HThread
{
protected:
	HRecord* pHRecord ; // HRecord from which HRecNotify is constructed
	HANDLE	 Event ;    // Same event for each notification

public:
	HRecNotify( HRecord* pHRecord );
	~HRecNotify();
	
	DWORD	ThreadProc();  // Procedure which is waiting for message
	HRESULT SetNotify( LPDIRECTSOUNDCAPTUREBUFFER m_pBuffer, DWORD dwNotifySize, int nbNotify ) ; // Apply notify recording events to the Buffer
} ;



//-----------------------------------------------------------------------------
// Name: class WSound
// Desc: Wrapper for class HSound and HListener
//-----------------------------------------------------------------------------
class WSound
{
public:
	HSound*		pHSound ;
	HListener*	pHListener ;
	ZSound*		pZSound ;		// used to insert sound or listener in 3D scene
	ZScene*		pZScene ;		// session in which sound or listener is
	DWORD		flag ;			// Flag used to create Direct Sound Buffer
	int			volume ;		// volume belong [0 100]
	int			pan ;			// panoramic belong [-100 100]
	bool		m_3dEnable ;	// 3D is enabled for user ( but may be disabled by system )

public:
	WSound( DWORD flag ) ;
	WSound( const WSound &w ) ; // copy constructor
	~WSound() ;

	HRESULT	SetVolume( int volume ) ;
	inline int  GetVolume() { return volume ; }
	HRESULT	SetPan( int pan ) ;	
	inline int	GetPan() { return pan ; }

	void    load(HSound* pHSound) ;
	void    load(HListener* pHListener) ;
	
} ;



//-----------------------------------------------------------------------------
// Name: class HSound
// Desc: Encapsulates functionality to play a sound with DirectSound.  
//-----------------------------------------------------------------------------
class HSound
{
public:
	WSound*					m_pWSound ;				// Wrapper

	LPDIRECTSOUNDBUFFER		m_pBuffer ;				// Direct Sound Buffer
	DWORD					m_dwDSBufferSize ;		// size of the buffer

	LPDIRECTSOUND3DBUFFER   m_p3DBuffer ;			// 3D sound buffer
	HSndNotify*				pHSndNotify ;			// thread that notify event coming from reading buffer
	
	int						m_volumeCone ;			
	
	WAVEFORMATEX*			m_pwfx;					// Pointer to WAVEFORMATEX structure, characteristic of audio data
	char*					m_fileName ;			// Path of the file
	DWORD					m_dwSize;				// size of data
	char*					m_nextFileName ;		// Path of a next file
	DWORD					m_nextSize;				// size for next data
	bool					m_nextUsed ;
	bool					m_nextState ;

	int						m_handlerEvtEnd ;		// if end data event is asked, handler used to activate callback
													
	bool					WaveType ;				// Hsound is a HWave
	bool					Mp3Type ;				// HSound is a HMp3
	short					DataType ;				// HSound is a HData ( value is AS_SND_CIRCULAR or AS_SND_LINEAR )
	bool					AudioType ;				// HSound is a HAudio ( used only for emulate old easySound lib )
													
	bool					m_streaming ;			// is it a streaming sound
	bool					m_loop ;				// sound replay when it is finished
	bool					m_playing ;				// remember that sound was playing when HSoundManager is disable
	bool					sndLocked ;				// used for critical sections between threads ( concurrent access to the Direct Sound Buffer )
	bool					isInList ;				// is this instance in list of HSound of HSoundManager
													
	long					m_lastPlayPos ;			// use to save the last reading position in the buffer
    DWORD					m_dwNotifySize ;		// size of data put in the direct sound buffer at each streaming notification ( m_dwNotifySize = m_dwDSBufferSize / NB_PLAY_NOTIFICATIONS )
    DWORD					m_dwNextWriteOffset ;	// Next position in the direct sound buffer to put data
	DWORD					m_dwReadOffset ;		// how much data has been read since the begining of data



public:
	HSound( bool addToList ) ;
	HSound( const HSound &h ) ;
	virtual ~HSound() ;

	HRESULT		CreateStatic( DWORD flag ) ;	// To create a static sound
	HRESULT     CreateStreaming( DWORD flag );  // To create a streaming sound
	HRESULT		Get3DBufferInterface();			// To create 3D capacity for sound

    HRESULT		FillBufferWithSound( long position, long sizeToFill ) ;  // Fill the buffer with data
	HRESULT		HandleStreamNotification() ;	// when HSndNotifyEvent is signaled, fill a size m_dwNotifySize in the buffer at position m_dwNextWriteOffset

	HRESULT		SetFrequency( int frequency ) ;
    DWORD		GetFrequency() ;
	HRESULT		Play( bool loop ) ; // Play sound from buffer
    HRESULT		Stop() ;  // Stop playing sound
    HRESULT		Reset() ; // Reset all settings for sound
    bool		IsSoundPlaying() ;
	HRESULT		SetPosition( long position, int flag ) ; // Set the read position in number of bytes
	DWORD		GetBufferPosition() ; // Get the read position in the buffer
	void		StopStreaming() ; // Stop the streaming of the sound

	void		Set3dMode( bool flag ) ; // Set 3D mode for Buffer 3D, flag is true or false
	HRESULT		SetVolumeCone( int volume ) ;	
	inline int  GetVolumeCone() { return m_volumeCone ; }

	void		SetNextFile( char* strFileName ) ;
	inline void	RemoveNextFile() { SAFE_DELETE( m_nextFileName) ; m_nextUsed = false ; }
	void		SwitchFile() ;
	void		ApplyFadeIn(  unsigned char* pBuffer, int size ) ;
	void		ApplyFadeOut( unsigned char* pBuffer1, int size1, unsigned char* pBuffer2, int size2 ) ;

	virtual DWORD	 GetPlayProgress() ; // Get size of data played in bytes
	virtual HRESULT	 Open( char* strFileName ) 										= 0 ;
	virtual HRESULT	 OpenNext( char* strFileName )									= 0 ;
	virtual DWORD	 Read( char* pBuffer, DWORD dwSizeToRead )						= 0 ;
    virtual HRESULT	 Close()														= 0 ;
    virtual HRESULT	 ResetFile()													= 0 ;  
	virtual HRESULT	 SetFilePosition( long position )								= 0 ;
	virtual HRESULT	 SetData( int channel, int bitPerSample, int freq, int flag )	= 0 ;
	virtual HRESULT	 AddData( char* data, unsigned int dataSize, int position )		= 0 ;
	virtual DWORD	 GetSizeMs()													= 0 ; // Get size of data in millisecondes
	virtual bool	 SameProperties( char* strFileName )							= 0 ;

protected:
	friend bool	operator != ( const WAVEFORMATEX &w1, const WAVEFORMATEX &w2 ) ;
};






//-----------------------------------------------------------------------------
// Name: class HWave
// Desc: Encapsulates reading sound data from a wave file
//-----------------------------------------------------------------------------
class HWave : public HSound
{
protected:
    HMMIO         m_hmmio;       // MM I/O handle for the WAVE
    MMCKINFO      m_ck;          // Multimedia RIFF chunk
    MMCKINFO      m_ckRiff;      // Multimedia RIFF chunk

protected:
    HRESULT ReadMMIO( WAVEFORMATEX* &pwfx, HMMIO &hmmio );
	HRESULT	Close() ;

public:
    HWave( bool addToList );
	HWave( HWave &h )  ;
    ~HWave();

	static bool  IsAWaveFile(char* fileName) ;
	bool SameProperties( char* strFileName ) ;

    HRESULT		 Open( char* strFileName ) ;
	HRESULT		 OpenNext( char* strFileName ) ;
	DWORD		 Read( char* pBuffer, DWORD dwSizeToRead );
	HRESULT		 ResetFile();
	inline int	 GetFilePosition() { return ( m_dwSize ? (m_dwSize - m_ck.cksize) : 0 ) ; }
	HRESULT		 SetFilePosition( long position ) ;
	inline DWORD GetSizeMs() { return  ( m_pwfx ? CharToMs( m_pwfx, m_dwSize ) : 0 ) ; }

	HRESULT		 SetData( int channel, int bitPerSample, int freq, int flag ) { return S_FALSE ; }
	HRESULT		 AddData( char* data, unsigned int dataSize, int position ) { return S_FALSE ; }

};




//-----------------------------------------------------------------------------
// Name: class Hmp3
// Desc: Encapsulates reading sound data from a mp3 file
//-----------------------------------------------------------------------------
class HMp3 : public HSound
{
protected:
	char			bufIn[FBSIZE];
	HANDLE			input_file ;
	VBRTAGDATA		current_vbrtag;
	id3tag			current_id3;
	int				nbMP3Err ;
	int				nbMP3OK ;

public:
	mp3info			cur_mp3info;
	mpstr*			m_mp3 ;
	int				decodeSize ;  // size of decoded data return at each success call to decodeMP3 methode

protected:
	static int	ExtractI4(unsigned char *buf) ;
	static bool	head_check(unsigned long head) ;
	static bool	head_check2(unsigned long head, mp3info *info) ;
	static int	GetVbrTag( VBRTAGDATA *pTagData, unsigned char *buf) ;
	static bool	GetMp3Info(HANDLE file, mp3info *info, id3tag *id3, VBRTAGDATA *vbr) ;
	static int	SeekPoint(unsigned char TOC[100], int file_bytes, float percent) ;
	long		GetNextFrame( long position ) ;
	long		GetFirstFrame( unsigned char* buffer, long size ) ;

public:
    HMp3( bool addToList ) ;
	HMp3( HMp3 &h ) ;
    ~HMp3();

	static bool  IsAMp3File(char* fileName) ;
	bool SameProperties( char* strFileName ) ;

	int			 GetFrameInfo( char* buffer, long size ) ;
    HRESULT		 Open( char* strFileName ) ;
	HRESULT		 OpenNext( char* strFileName ) ;
	HRESULT		 Close() ;
	DWORD		 Read( char* pBuffer, DWORD dwSizeToRead ) ;
	HRESULT		 ResetFile() ;  
	HRESULT		 SetFilePosition( long position ) ;
	DWORD		 GetSizeMs() { return cur_mp3info.length ; }

	HRESULT		 SetData( int channel, int bitPerSample, int freq, int flag ) { return S_FALSE ; }
	HRESULT		 AddData( char* data, unsigned int dataSize, int position ) { return S_FALSE ; }

};





//-----------------------------------------------------------------------------
// Name: class HData
// Desc: Encapsulates reading sound data
//-----------------------------------------------------------------------------
class HData : public HSound
{
protected:
	lbuffers*	head ;  // head of the chained list of data
	lbuffers*	queue ; // queue of the chained list of data
	lbuffers**	curs ;  // used only by AS_SND_CIRCULAR
	DWORD		flag ;  // AS_SND_CIRCULAR or AS_SND_LINEAR

protected:
	HRESULT	 Close() ;
	void	 RemoveData( lbuffers* &ptr, int position ) ;
	void	 FreeBuffers(lbuffers* &head) ;
	void	 InitBuffers(lbuffers* h) ;
	DWORD	 ReadLinear( char* pBuffer, unsigned long sizeToRead ) ;
	DWORD	 ReadCircular( char* pBuffer, unsigned long sizeToRead ) ;

public:
    HData( bool addToList );
	HData( HData &h ) ;
    ~HData();

	HRESULT		 SetData( int channel, int bitPerSample, int freq, int flag ) ;
	HRESULT		 AddData( char* data, unsigned int dataSize, int position ) ;
	void		 CopyData( lbuffers* h ) ;
	HRESULT		 ResetFile();
	HRESULT		 SetFilePosition( long position ) ;
	DWORD		 GetPlayProgress() ;
	HRESULT		 Open( char* strFileName ) { return S_FALSE ; }
	HRESULT		 OpenNext( char* strFileName ) { return S_FALSE ; }
	bool		 SameProperties( char* strFileName ) { return false ; }

	inline DWORD GetSizeMs() { return ( m_pwfx ? CharToMs( m_pwfx, m_dwSize ) : 0 ) ; }
	inline DWORD Read( char* pBuffer, DWORD sizeToRead ) { return ( DataType & AS_SND_LINEAR ? ReadLinear( pBuffer, sizeToRead ) : ReadCircular( pBuffer, sizeToRead ) ) ; }

};



//-----------------------------------------------------------------------------
// Name: class HAudio
// Desc: Made to emulate EasySound Library
//-----------------------------------------------------------------------------
class HAudio : public HSound
{
protected:
	HRESULT		 Close() ;

public:
    HAudio( bool addToList );
    ~HAudio();

	HRESULT	  SetData( int channel, int bitPerSample, int freq, int size ) ;
	DWORD	  Read( char* pBuffer, DWORD sizeToRead ) ;
	HRESULT   Open( char* strFileName ) { return S_FALSE ; }
	HRESULT	  OpenNext( char* strFileName ) { return S_FALSE ; }
	HRESULT	  ResetFile() { return S_OK ; }
	HRESULT	  SetFilePosition( long position ) { return S_FALSE ; }
	HRESULT	  AddData( char* data, unsigned int dataSize, int position ) { return S_FALSE ; }
	bool	  SameProperties( char* strFileName ) { return false ; }

	inline DWORD  GetSizeMs() { return ( m_pwfx ? CharToMs( m_pwfx, m_dwSize ) : 0 ) ; }
};



//-----------------------------------------------------------------------------
// Name: class HRecorder
// Desc: Encapsulates functionality to record a sound with DirectSound.  
//-----------------------------------------------------------------------------
class HRecord
{
protected:
	LPDIRECTSOUNDCAPTURE       m_pDSCapture  ;  // Direct Sound Capture
	LPDIRECTSOUNDCAPTUREBUFFER m_pBuffer ;		// Direct Sound Capture Buffer
	HRecNotify*				   m_pHRecNotify ;	// thread that notifies events for streaming

	DWORD m_BufferSize ;			// size of buffer
	DWORD m_NextCaptureOffset ;		// Next position in the direct sound capture buffer to write data
	short m_bitPerSample ;			// SampleRate 8 or 16 bits
	float m_seuil ;					// Threshold Volume to detect no speeching
	short m_retard ;				// use to not stop recording too early
	int   m_obj ;					// used to send an event to leading thread to activate callback

public:
	WAVEFORMATEX*	m_pwfx ;		// Pointer to WAVEFORMATEX structure, characteristic of audio data
	char*			out ;			// data that was recorded
	DWORD			m_NotifySize ;  // size of data put in the direct sound capture buffer at each streaming notification ( m_dwNotifySize = m_dwDSBufferSize / NB_REC_NOTIFICATIONS )

protected:
	bool	IsSpeeching( unsigned char* pBuffer, unsigned long size ) ; // Detect if the power of the signal is above a threshold of power
	void	Release() ; // Release the sound recorder
	
public:
	HRecord() ;
	~HRecord() ;

	HRESULT Init( int nbChannels, int bitPerSample, int frequence, int volume ) ;	// Setting the sound recorder
	HRESULT Create( int size, int obj ) ; // Create the sound recorder
	HRESULT Start() ;	// start recording					
	HRESULT Stop() ;	// stop recording
	int		RecordCapturedData() ; // call by thread to store blocks recorded
	bool	IsRecording() ;
	
} ;





//-----------------------------------------------------------------------------
// Name: class HListener
// Desc: Encapsulates properties of a 3D listener
//-----------------------------------------------------------------------------
class HListener
{
public:
	static LPDIRECTSOUND3DLISTENER	m_pListener ;
	static ZScene* activeScene ;

public:
	HListener() ;
	~HListener() ;

	void SetActive( ZScene* pZScene, ZSound* pZSound ) ;
};



#endif