// smfplay.cpp & smfformat.cpp // ショートイベントを格納する typedef struct tagMIDISTREAMEVENT{ DWORD dwDeltaTime; DWORD dwStreamID; DWORD dwEvent; }MIDISTRMEVENT; // 線形リストを構築する typedef struct tagMIDI{ tagMIDI *pNext; // 次のリスト DWORD dwSumTime; // 絶対時間 BYTE dwEvent[1]; // 可変長に確保する }MIDI; class SmfFormat{ // メソッド MIDI** ConvertStage1(BYTE *pData,DWORD *nSumEvent); MIDI** ConvertStage2(BYTE *pData,MIDI **midiList,DWORD nSumEvent); BYTE* ConvertStage3(BYTE *pData,MIDI **midiArray,DWORD nSumEvent); BYTE* Convert(BYTE *pData); // フォーマット1をフォーマット0(ランニングステータス補完)に変換する BYTE* Initialize(BYTE *pData); void ComputeEndTime(BYTE *pData,MIDI **midiArray,DWORD nSumEvent); protected: // メンバ変数 BYTE *m_pMidi; // MIDIの先頭アドレス double m_endTime; // 終了時刻(秒単位) // メソッド BYTE Encode(BYTE *variable,DWORD fixed); BYTE Decode(BYTE *variable,DWORD *fixed); public: SmfFormat(char *rscName,char *rscType); // リソース SmfFormat(char *fileName); // ファイル SmfFormat(BYTE *pData); // データ(SMFのデータ形式に従っている必要があります) ~SmfFormat(void); void CreateSMF(char *fileName); // 標準MIDIファイル(SMF)を作成する(ランニングステータスを補完したフォーマット0) // 拡張子も付けて下さい }; class SmfPlay : public SmfFormat{ // 列挙体 enum SMFPLAYCONDITION{ STOP,PLAY,PAUSE }; // メンバ変数 HMIDISTRM m_hStream; MIDIHDR *m_pMidiHdr; BYTE m_bufsum; // m_pMidiHdr の個数 DWORD m_bufsize; // m_pMidiHdr->lpData のバイト数 DWORD m_offset; // MIDIの先頭から次に読み込みを開始する位置までのバイト数 SMFPLAYCONDITION m_condition; // 演奏状態 HANDLE m_hThread; // コールバックスレッドのハンドル // メソッド DWORD Sysexc(DWORD deltaTime,BYTE *p,LPSTR pMidiBuf,DWORD *written); DWORD Meta(DWORD deltaTime,BYTE *p,LPSTR pMidiBuf,DWORD *written); DWORD ShortEvent(DWORD deltaTime,BYTE *p,LPSTR pMidiBuf,DWORD *written); DWORD EndOfTrack(DWORD deltaTime,BYTE *p,LPSTR pMidiBuf,DWORD *written); DWORD TrackChunk(BYTE *p,MIDIHDR *pMidiHdr); void MsgBox(MMRESULT result,char *caption); void StreamOut(void); void Initialize(void); // 静的メソッド static DWORD WINAPI ThreadProc(void *lpParameter); // コールバックスレッド public: SmfPlay(char *rscName,char *rscType); // リソース SmfPlay(char *fileName); // ファイル SmfPlay(BYTE *pData); // データ(SMFのデータ形式に従っている必要があります) ~SmfPlay(void); void Play(void); // 再生開始します(一時停止を解除します) // 最後まで演奏した場合は自動的に停止します(再生開始位置を先頭にシークする) void Stop(void); // 停止します(再生開始位置を先頭にシークする) void Pause(void); // 一時停止します MMRESULT GetCurrentPosition(LPMMTIME lpmmt,UINT cbmmt); // midiStreamPosition 関数を呼び出します double GetEndTime(void); // 終了時刻(秒単位)を取得します };