#include"CSoundDecoderWave.h"
#include"../../../auxiliary/CString.h"
#include"../../../auxiliary/Macro.h"
#include"../../../auxiliary/Debug/CAssert.h"
#include"../../../auxiliary/Debug/CWarning.h"
#include"../../../auxiliary/Debug/CException.h"


namespace Maid
{
	/*!
	 	@class	CSoundDecoderWave CSoundDecoderWave.h
	 	@brief	WAVE ファイルエンコーダー
	 */
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! コンストラクタ
/*!
 */
CSoundDecoderWave::CSoundDecoderWave()
{
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! デストラクタ
/*!
 */
CSoundDecoderWave::~CSoundDecoderWave()
{
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ファイルのロード
/*!
 	引数などは ISoundDecoder::Open を参照すること
 */
void CSoundDecoderWave::Open( const mstring& FileName )
{
	Close();

	m_hFile.Open( FileName );

	MySTL::vector<unt08> tmp(2048);	//	これで十分でしょう
	m_hFile.Read( &(tmp[0]), (int)tmp.size() );

	if( (*(unt32*)(&tmp[0]))!=Str2Binary32('R','I','F','F') ||
		(*(unt32*)(&tmp[8]))!=Str2Binary32('W','A','V','E')  ) { MAID_THROWEXCEPTION( MAIDTEXT("waveファイルでありません") ); }

	unt32 sample;
	{
		unt08*	pNow = &(tmp[12]);
		unt32	dwOffset = 12;

		bool bfmt = false;
		bool bdata= false;
		while( true )
		{
			if( bfmt && bdata ) { break; }

			unt32 type   = *((unt32*)pNow);
			unt32 length = *((unt32*)(pNow+4));

			if( type==Str2Binary32('f','m','t',' ') )
			{
				unt08* pData  = pNow+8;
				memcpy( &m_WaveFormat, pData, length );
				bfmt = true;
			}else if( type==Str2Binary32('d','a','t','a') )
			{
				sample   = length;
				m_BeginOffset = dwOffset+8;
				bdata = true;
			}

			pNow += length+8;
			dwOffset += length+8;
		}

	}

	m_PCMLength = sample;
	m_hFile.Seek( m_BeginOffset, IFileRead::POSITION_BEGIN );
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! デコードする
/*!
 	引数などは ISoundDecoder::Read を参照すること
 */
int CSoundDecoderWave::Read( void* pDst, int dwSize )
{
	const unt32 pos = GetPosition();
	const unt32 len = GetLength();

	unt32 Red;

	if( pos+dwSize < len )	{ Red = dwSize; }
	else	
	{
		Red = len - pos; 
	}

	return m_hFile.Read( pDst, Red ) ;

}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! デコード開始位置を移動する
/*!
 	引数などは ISoundDecoder::SetPosition を参照すること
 */
void CSoundDecoderWave::SetPosition( int Offset, POSITION ePos )
{
	IFileRead::POSITION FilePos;

	switch( ePos )
	{
	case ISoundDecoder::BEGIN:	{ FilePos = IFileRead::POSITION_BEGIN;	}break;
	case ISoundDecoder::END:	{ FilePos = IFileRead::POSITION_END;	}break;
	case ISoundDecoder::CURRENT:{ FilePos = IFileRead::POSITION_CURRENT;}break;
	}
	m_hFile.Seek( m_BeginOffset+Offset, FilePos );
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 読み込んだファイルの解放
/*!
 	引数などは ISoundDecoder::Close を参照すること
 */
void	CSoundDecoderWave::Close()
{
	m_hFile.Close();
	ZERO( &m_WaveFormat, sizeof(m_WaveFormat) );
	m_PCMLength   = 0;
	m_BeginOffset = 0;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 現在の位置の取得
/*!
 	引数などは ISoundDecoder::GetPosition を参照すること
 */
int	CSoundDecoderWave::GetPosition()		const
{
	const unt32 FilePos = m_hFile.GetPosition();

	return FilePos-m_BeginOffset;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! コンバート後のファイルの長さを取得する（バイト単位）
/*!
 	引数などは ISoundDecoder::GetLength を参照すること
 */
int	CSoundDecoderWave::GetLength()			const
{
	return m_PCMLength;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! １秒あたり何サンプルあるかの取得
/*!
 	引数などは ISoundDecoder::GetSamplesPerSec を参照すること
 */
int	CSoundDecoderWave::GetSamplesPerSec()	const
{
	return m_WaveFormat.nSamplesPerSec;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! チャンネル数(mono,stereo 等)の取得
/*!
 *	引数などは ISoundDecoder::GetChannels を参照すること
 */
int	CSoundDecoderWave::GetChannels()		const
{
	return m_WaveFormat.nChannels;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! １サンプルあたりに使用しているビット量の取得
/*!
 *	引数などは ISoundDecoder::GetBitsPerSamples を参照すること
 */
int	CSoundDecoderWave::GetBitsPerSamples()	const
{
	return m_WaveFormat.wBitsPerSample;
}



}
