/*
	author:		qE.77T.ink
	License:	Public Domain
	
	Revision:	1.01
	
	qE.77T.ink 偑婲偙偟偨僐乕僪偵娭偟偰偼挊嶌尃偼庡挘偟側偄偺偱
	帺桼偵巊梡偟偰栤戣側偄傛
	
	懡暘丄偙偺傑傑偙偺僋儔僗傪巊梡偡傞偲 BonTsEngine 偺 GPL 偵姶愼偡傞偲巚偆
	偙偺僐乕僪偵棳梡偡傞傎偳偺壙抣偑偁傞偲偼巚偊側偄偗傟偳傕丒丒丒('A`)
*/
#pragma once

#include "FileWriter.h"

#include <vector>

/*	
	僩儕僢僾偺 namespace 偲偐僙儞僗偑媈傢傟傞丒丒丒
	椙偄 namespace 巚偄偮偐側偐偭偨傫偩傛丒丒丒杮摉偩傛('A`)
	偁偀丒丒丒偦偙丄暔傪搳偘側偄偱丒丒丒('A`)
*/
namespace qE77Tink{ //	qE.77T.ink

//	伀昁梫側偄傫偩偗偳堦墳丒丒丒
#include <pshpack1.h>
/*
	http://www.ebu.ch/CMSimages/en/tec_doc_t3306-2007_tcm6-42570.pdf?display=EN
*/
// declare RiffChunk structure
struct RiffChunk{
	char chunkId[4];			// 乪RIFF乫
	unsigned long chunkSize;	// 4 byte size of the traditional RIFF/WAVE file
	char riffType[4];			// 乪WAVE乫
};

// declare JunkChunk structure
struct JunkChunk{
	char chunkId[4];		// 乪JUNK乫
	unsigned int chunkSize;	// 4 byte size of the 乪JUNK乫 chunk. This must be at
	// least 28 if the chunk is intended as a
	// place-holder for a 乪ds64乫 chunk.
//	char chunkData[];		// dummy bytes
};

// declare FormatChunk structure
struct FormatChunk{
	char chunkId[4];				// 乪fmt 乫
	unsigned long chunkSize;		// 4 byte size of the 乪fmt 乫 chunk
	unsigned short formatType;		// WAVE_FORMAT_PCM = 0x0001, etc.
	unsigned short channelCount;	// 1 = mono, 2 = stereo, etc.
	unsigned long sampleRate;		// 32000, 44100, 48000, etc.
	unsigned long bytesPerSecond;	// only important for compressed formats
	unsigned short blockAlignment;	// container size (in bytes) of one set of samples
	unsigned short bitsPerSample;	// valid bits per sample 16, 20 or 24
	unsigned short cbSize;			// extra information (after cbSize) to store
	char extraData[22];				// extra data of WAVE_FORMAT_EXTENSIBLE when necessary
};

// declare DataChunk structure
struct DataChunk{
	char chunkId[4];			// 乪data乫
	unsigned long chunkSize;	// 4 byte size of the 乪data乫 chunk
//	char waveData[];			// audio samples
};

// declare RF64Chunk structure
struct RF64Chunk{
	char chunkId[4];			// 乪RF64乫
	unsigned long chunkSize;	// -1 = 0xFFFFFFFF means don乫t use this data, use
	// riffSizeHigh and riffSizeLow in 乪ds64乫 chunk instead
	char rf64Type[4];			// 乪WAVE乫
};

// declare ChunkSize64 structure
struct ChunkSize64{
	char chunkId[4]; 				// chunk ID (i.e. 乬big1乭   this chunk is a big one)
	unsigned long chunkSizeLow;		// low 4 byte chunk size
	unsigned long chunkSizeHigh;	// high 4 byte chunk size
};

// declare DataSize64Chunk structure
struct DataSize64Chunk{
	char chunkId[4];				// 乪ds64乫
	unsigned long chunkSize;		// 4 byte size of the 乪ds64乫 chunk
	unsigned long riffSizeLow;		// low 4 byte size of RF64 block
	unsigned long riffSizeHigh;		// high 4 byte size of RF64 block
	unsigned long dataSizeLow;		// low 4 byte size of data chunk
	unsigned long dataSizeHigh;		// high 4 byte size of data chunk
	unsigned long sampleCountLow;	// low 4 byte sample count of fact chunk
	unsigned long sampleCountHigh;	// high 4 byte sample count of fact chunk
	unsigned long tableLength;		// number of valid entries in array 乬table乭
//	chunkSize64 table[];
};
#include <poppack.h>

/*
	Wav 弌椡

	4GB <=	丗 RIFF
	4GB >	丗 RF64
*/
class WavWriter : public CFileWriter{
	protected:
		std::vector<BYTE>		m_RiffHeader;
		bool					m_bForceRiff;
	public:
		WavWriter(CDecoderHandler *pDecoderHandler);
		virtual	~WavWriter();
	
		virtual	const bool	OpenFile(LPCTSTR lpszFileName, WORD wBitsPerSample, WORD wChannel, DWORD dwSamplesPerSec, bool bForceRiff = false);
	
		/*
			CFileWriter 偵 virtual 懏惈晅偄偰側偄偺偁傞偐傜
			傾僢僾僉儍僗僩偝傟傞偲僗乕僷乕僋儔僗偑屇偽傟偰摦偐側偄傛('A`)
		*/
		virtual	const bool	OpenFile(LPCTSTR lpszFileName);
		virtual	void		CloseFile(void);
		virtual const bool	InputMedia(CMediaData *pMediaData, const DWORD dwInputIndex = 0UL);
};

/*
	Wav 暘妱弌椡

	僠儍儞僱儖枅偵 wav 壔

	4GB <=	丗 RIFF
	4GB >	丗 RF64
*/
class WavSplitWriter : public CMediaDecoder{
	protected:
		std::vector<WavWriter*>		m_OutFiles;
		DWORD						m_dwBlockAlign;
	public:
		WavSplitWriter(CDecoderHandler *pDecoderHandler);
		virtual	~WavSplitWriter();
		
		virtual	const bool	OpenFile(LPCTSTR lpszFileName, WORD wBitsPerSample, WORD wChannel, DWORD dwSamplesPerSec, bool bForceRiff = false);
		virtual	void		CloseFile(void);
	
		//	IMediaDecoder
		virtual void		Reset(void);
		virtual const DWORD GetInputNum(void) const;
		virtual const DWORD GetOutputNum(void) const;
		virtual const bool	InputMedia(CMediaData *pMediaData, const DWORD dwInputIndex = 0UL);
};
	
}//	End of namespace qE77Tink
