///////////////////////////////////////////////////
// filename:MP3Audio.h
// author: Chafumi Touji
// version: 1.0.1
// date: 2018/09/27
//		 2020/02/04
///////////////////////////////////////////////////

#ifndef __MP3AUDIO_H__
#define __MP3AUDIO_H__

typedef struct{

	char		Identifier[3];
	char		Version[2];
	char		Flag;
	unsigned char TagSize[4];

} ID3HEADER;

typedef struct{

	char		FrameID[4];
	unsigned char		FrameSize[4];
	char		Flag[2];

} ID3FRAMEHEADER;

typedef struct{

	char		FrameID[4];
	int		FrameSize;
	char		*Data;

} ID3FRAMEDATA;

typedef struct{

	int		BitRate;
	int		SamplingRate;
	char		Padding;
	char		ChannelMode;

} MP3FORMATINFO;

class CMP3Audio{
private:
	int												ID;
	int												StartID;
	HWND											ParentWnd;
	HMMIO											hmmio;
	HACMSTREAM								HAS;
	ACMSTREAMHEADER					ASH;
	LPDIRECTSOUNDBUFFER				lpDSoundBufferSecondary;
	LPMPEGLAYER3WAVEFORMAT		WFE_MP3;
	LPWAVEFORMATEX						WFE_Secondary;
	HANDLE										Thread;
	char												*StreamBuffer;
	char												*SampleBuffer;
	int												Status;
	int												PlayingPos;
	int												MP3Offset;
	int												WaveBlockSize;
	int												MP3Size;
	int												WaveSize;
	int												Pos;
	int												TotalTime;
	int												WaveDataMargin;
	bool												Loop;
	double											Volume;
	bool												PlayOnce;

public:
	CMP3Audio();
	~CMP3Audio();
	bool Open(CPCMAudio *audio, wchar_t *filename, HWND parent_wnd, int id, int start_id );
	bool Play();
	bool Pause();
	bool Stop();
	bool Close();
	bool Mute(bool do_mute);
	bool Seek(double pos);
	int GetStatus();
	int GetTotalTime();
	double GetPlayingTime();
	double GetPlayPos();
	double GetVolume();
	int GetBufferPos();
	bool SetVolume(double volume, bool is_mute );
	bool SetLoop(bool loop);
	bool GetLoop();
	bool SetPlayOnce(bool play_once);
	bool GetPlayOnce();
	bool GetSample(int *sample_left, int *sample_right, int sample_count);
	int GetID(){ return ID; };

private:
	bool ReadMP3FormatInfo(MP3FORMATINFO *format_info);
	bool InitMP3DecodeStream(WAVEFORMATEX *src_wfe, WAVEFORMATEX *dest_wfe);
	int mmioReadMP3(HMMIO hmmio, char *pMem, int request_size);
	bool CreateMP3SoundBuffer(LPDIRECTSOUND lpDSound, LPDIRECTSOUNDBUFFER *lpBuffer, LPWSTR filename);
	static unsigned __stdcall  ThreadMP3Stream(LPVOID pParam);
	bool BeginStreamMP3();
};

#endif