#ifndef mp3infoH
#define mp3infoH
#include "vbrinfo.h"

class IKpiFile;
class IKpiTagInfo;
class MP3Info
{
private:
    IKpiFile *m_pFile;
    VBRTAGINFO m_vbrTag;
    INT64 m_file_start;  //先頭位置（同期ヘッダが見つかった最初の位置）
    INT64 m_file_end;    //終端位置（最終フレームの終端の筈の位置）
    INT64 m_file_pointer;//ファイルポインタ
    //先頭のフレームヘッダの情報の一部
    //(2つ目以降で m_mpg25/m_lsf/m_lay/m_freq/m_nch のいずれかの値が異なっているフレームは異常と見なす)
    int  m_mpeg25;        //MPEG2.5(1 or 0)
    int  m_lsf;           //LSF(1 or 0)
    int  m_lay;           //Layer(1 or 2 or 3)
    int  m_freq;          //再生周波数
    int  m_nch;           //チャネル数(1or2)
    int  m_mode;
    //
    bool   m_hasVbrtag;     //VBR タグがあれば 1
    int    m_bitrate;       //ビットレート
    int    m_dec_delay;     //decoder delay
    int    m_enc_delay;     //encoder delay
    int    m_enc_padding;   //encoder padding
    DWORD  m_dwStartSample; //開始位置(デコード結果はここから使用)(LAME タグ有効時のみ使用)
    UINT64 m_qwEndSample;   //終端位置(デコード結果はここまで使用)(LAME タグ有効時のみ使用)
    UINT64 m_qwLength100ns; //曲の長さ(100ns単位)
    UINT64 m_qwCurrentFrame;//現在のフレーム位置
    DWORD  m_frame_samples; //1フレーム当たりのサンプル数
    enum{
        MAX_FRAMESIZE = 4096, //1フレーム当たりの最大サイズ(frame.h の MAXFRAMESIZE) 実際は 1726 で十分？
    };
    BYTE  m_PrevBuf[MAX_FRAMESIZE];//前回 ReadFrames 呼び出し時に pBuffer に返せなかったフレームデータの一部
    DWORD m_dwPrevBufLen;          //↑の有効な部分のサイズ
    struct SEEK_TABLE//高速シーク用テーブル
    {
        UINT64 qwPosFrame;    //再生位置(フレーム単位)
        UINT64 qwFilePointer; //ファイル位置（未登録の場合は0）
    }*m_pSeekTable;
    int  m_nTableSize;//シークテーブルのサイズ（実際にシークするまで作らない）

    int   FileRead(void *pBuffer, int nSize);
    INT64 FileSeek(INT64 position, DWORD method);
public:
    BOOL GetMp3Info(IKpiFile *pFile);
    void GetVbrTagInfo(const VBRTAGINFO **cppTagInfo){
        if(m_hasVbrtag){*cppTagInfo = &m_vbrTag;}
        else{*cppTagInfo = NULL;}
    }
    UINT64 GetEndSample(void)const{return m_qwEndSample;}
    DWORD  GetStartSample(void)const{return m_dwStartSample;}
    int    GetChannels(void)const{return m_nch;}
    int    GetSampleRate(void)const{return m_freq;}
    DWORD  GetFrameSamples(void)const{return m_frame_samples;}
    UINT64 GetLength100ns(void)const{return m_qwLength100ns;}
    int    GetBitrate(void)const{return m_bitrate;}
    int    GetDecDelay(void)const{return m_dec_delay;}
    int    GetEncDelay(void)const{return m_enc_delay;}
    int    GetEncPadding(void)const{return m_enc_padding;}
    int    GetLayer(void)const{return m_lay;}
    int    GetStereoMode(void)const{return m_mode;}
    int    GetMpeg(void)const{return m_mpeg25 ? 2 : m_lsf;}//0:MPEG1.0 1: MPEG2.0 2: MPEG2.5
   
    UINT64 _100nsToSample(UINT64 qw100ns)const{return qw100ns * m_freq / (1000*10000);}
    UINT64 SampleTo100ns(UINT64 qwSample)const{return qwSample * (1000*10000) / m_freq;}
    UINT64 SampleToByte(UINT64 qwSample, DWORD dwBps)const{return qwSample * (dwBps/8) * m_nch;}
    UINT64 ByteToSample(UINT64 qwByte, DWORD dwBps)const{return qwByte / ((dwBps/8) * m_nch);}

    UINT64 Mp3SeekSample(UINT64 qwPosSample);//引数、戻り値ともにサンプル単位、戻り値はシーク後の位置
    DWORD ReadFrames(BYTE* pBuffer, DWORD dwBufSize, BOOL *pbEof);
    BOOL  __fastcall GetTagInfo(IKpiTagInfo *pInfo, DWORD dwTagGetFlags);
    MP3Info(void);
    ~MP3Info(void);
};
#endif