#ifndef __INCLUDE_DRIFF_H__
#define __INCLUDE_DRIFF_H__
//-----------------------------------------------------------------
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <windows.h>
#include <vfw.h>
#include <mmsystem.h>
#include <mmreg.h>
#include <msacm.h>
//-----------------------------------------------------------------
// for VC++ link library
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "vfw32.lib")
#pragma comment(lib, "msacm32.lib")
//-----------------------------------------------------------------
#define BMPLL(bih) (((bih->biWidth*bih->biBitCount+31)&~0x1f)*bih->biPlanes/8)
#define DRIFF_WAVE mmioFOURCC('W','A','V','E')
#define DRIFF_AVI  mmioFOURCC('A','V','I',' ')
#define DRIFF_WIN  1000
#define DRIFF_MP3  1001
#define FFT_PI     3.141592653589793 // pi to machine precision in math.h
#define FFT_TWOPI  (2.0*FFT_PI)
#define PW(x,y)    (sqrt(x*x+y*y))
//#define MP3_BLOCK_SIZE 522
//-----------------------------------------------------------------
// 変数宣言
//-----------------------------------------------------------------
enum WAVE_DRAW_TYPE {
    DGW_NORMAL = 0,
    DGW_FFT    = 1,
};
struct DRIFF_HEAD { DWORD ckID,ckSize; };
struct complex    { double re,im;      };
extern HDRAWDIB dg_DDib;
//-----------------------------------------------------------------
// MP3 info.
//-----------------------------------------------------------------
enum MPEG_VERSION {
    MPEG25   = 0,
    NOT_MPEG = 1,
    MPEG2    = 2,
    MPEG1    = 3,
};
enum MPEG_LAYER {
    MPEG_LAYER1 = 3,
    MPEG_LAYER2 = 2,
    MPEG_LAYER3 = 1,
    NOT_LAYER   = 0,
};
//-----------------------------------------------------------------
// グローバル定義用データ
//-----------------------------------------------------------------
class CDG_Global {
 public:
    DWORD dg_type;
    POINT ds;
    int g_mp3Drivers;
    int dgw_type,avi_audio;
    int wave_hlz,wave_bit,wave_chn;
    double waittime;
    char dg_fname[MAX_PATH];
    HWND AppHwnd,edHwnd;
    HANDLE dg_hthr;
    LPBITMAPINFOHEADER dibh;
 public:
    CDG_Global() {
        dg_type   = 0;
        dgw_type  = DGW_NORMAL;
        avi_audio = FALSE;
        wave_hlz  = 0;
        wave_bit  = 0;
        wave_chn  = 0;
        waittime  = 0.;
        g_mp3Drivers = 0;
 }
};
//-----------------------------------------------------------------
// 一般関数
//-----------------------------------------------------------------
int err_check(MMRESULT mmr);
BOOL CALLBACK acmDrvFind(HACMDRIVERID hadid,DWORD dwInst,DWORD fdwSupport);
void TRACE(char *fmt,...);
void err_avi(int err);
int  check_suffix(char* filename,char* ext);
void set_win(HWND mwh,HWND edwh);
void set_info(char* sbuf);
void cat_info(char* sbuf);
char* getfps();
int  dg_fileopen(HWND hWnd);
void dg_close();
void dg_isave(HWND hWnd);
UINT SaveBMP(char* filename,LPBYTE lpBuf);
void set_wavedraw(int dgw);
DWORD DG_thread(HWND hWnd);
void dg_draw(HWND hWnd);
void dg_wavein(HWND hWnd);
void dg_windraw(HWND hWnd);
void dg_woutplay();
//-----------------------------------------------------------------
// Class of AVI draw graphic and playing wave(PCM) sound
//-----------------------------------------------------------------
class DRIFF {
 private:
    FILE *file;
    DRIFF_HEAD head[16];
    DWORD type;
    struct {
        LPBITMAPINFOHEADER pbmih;
        PAVIFILE    file;
        PAVISTREAM  ps_audio,ps_autmp;
        PAVISTREAM  ps_movie;
        PGETFRAME   movie_frame;
        AVIFILEINFO info;
        AVISTREAMINFO si;
        HIC hicd;
        LPBITMAPINFOHEADER lpSrcFmt,lpDecFmt;
        LPBYTE lpSrc,lpDec;
        LONG lLength,FmtLeng;
        long current_samples;
        int eof;
        int init_flag;
        int codec;
    } movie;
    struct {
        WAVEFORMATEX format;
        WAVEFORMATEX *format_src;
        int  block_size;
        int  start_pos;
        long current_samples;
        int  eof;
        char *buf;
        int  init_flag,in_flag;
        int  dgw_size;
        float *fft;
    } wave;
    struct {
        WAVEHDR **FIWaveHdr,**FOWaveHdr;
        HWAVEIN  FHWaveIn;  // WAVE IN ハンドル
        HWAVEOUT FHWaveOut; // WAVE OUT ハンドル
        DWORD volume;
        int in_count,out_count;
        int in_current,out_current;
    } waveio;
    struct {
        char *buf,*buf_read;
        char *buf_p;
        char *buf_read_p;
        DWORD buf_size;
        int   buf_left;
        int   read_size;
        HACMSTREAM      acm;
        ACMSTREAMHEADER ach;
        MPEGLAYER3WAVEFORMAT* format_src;
        int flag;
    } acm;
 public:
    int Open(char *filename);
    DRIFF();
    ~DRIFF();
    int Close();
    int Seek(double sec);
    int GetType();
    //--------------------------------------------------
    // AVI 画像関数
    //--------------------------------------------------
    int AviOpen(char *filename);
    int codecOpen();
    double AviGetFps();
    POINT* AviGetSize();
    int AviGetCount();
    int AviGetFrame(int a,void **data);
    int AviEof();
    int AviRead(void **data);
    int AviRead2(void **data);
    int AviSeek(double sec);
    int AviClose();
    //--------------------------------------------------
    // WAVE 音声関数
    //--------------------------------------------------
    void WaveInfo(char* buf,WAVEFORMATEX f);
    int WaveOpen(char* filename);
    int WaveClose();
    int WaveInit(WAVEFORMATEX f);
    int WavePos(double sec);
    int WaveSeek(double sec);
    int WavePlay(void *buffer,int size,int wait);
    int WavePlay(double sec,int wait);
    int WaveEof();
    int WaveRead(void *buffer,int size);
    int WaveBlockSize(WAVEFORMATEX f);
    int WaveRead2(void *buffer,int samples);
    //--------------------------------------------------
    // WAVE 出力関数
    //--------------------------------------------------
    int WaveOutInit();
    int WaveOutOpen(WAVEFORMATEX *format,int bufsize,int count);
    int WaveOutPlay(void *buffer,int size,int wait);
    int WaveOutClose();
    //--------------------------------------------------
    // WAVE 入力関数
    //--------------------------------------------------
    int WaveInInit();
    int WaveInOpen();
    int WaveInPlay();
    int WaveInClose();
    //--------------------------------------------------
    // ACM 音源
    //--------------------------------------------------
    int AcmOpen(WAVEFORMATEX f);
    int AcmConvert(void *src,int src_size,void *dest,int dest_size);
    int AcmClose();
    int AcmRead(void *buf,int size);
    int AcmBufferClear();
    //--------------------------------------------------
    // MP3 出力関数
    //--------------------------------------------------
    int MP3Open(char* filename);
    int MP3Info(char* filename,MPEGLAYER3WAVEFORMAT* mp3fmt);
    //--------------------------------------------------
    // WAVE 波形表示
    //--------------------------------------------------
    BOOL DrawWave(HDC hDC,RECT *pR);
    int FFT();
};

#endif //__INCLUDE_DRIFF_H__