//******************************************************************************
//
// Simple MIDI Library / SMTrack
//
// トラッククラス
//
// Copyright (C) 2010-2017 WADA Masashi. All Rights Reserved.
//
//******************************************************************************

// MEMO:
// SysEXイベントとメタイベントは可変長サイズのため、単純リストクラスを
// そのまま利用できない。しかしこれらのイベントは、必ず4byteに収まるMIDI
// イベントに比べて圧倒的に少ないので、個々にnewされることを容認し、
// mapで管理する。
//
// TODO:
// SMEventクラスにデルタタイムとポート番号を持たせるべき。
// イベント／デルタタイム／ポート番号を分離しているため、
// SMTrackクラス利用者の処理が煩雑になっている。

#import "SMSimpleList.h"
#import "SMEvent.h"
#import "SMNoteList.h"
#import <map>

#pragma warning(disable:4251)


//******************************************************************************
// トラッククラス
//******************************************************************************
class SMTrack
{
public:
	
	//コンストラクタ／デストラクタ
	SMTrack(void);
	virtual ~SMTrack(void);
	
	//クリア
	void Clear();
	
	//データセット登録
	int AddDataSet(unsigned int deltaTime, SMEvent* pEvent, unsigned char portNo);
	
	//データセット取得
	int GetDataSet(unsigned int index, unsigned int* pDeltaTime, SMEvent* pEvent, unsigned char* pPortNo);
	
	//データセット数取得
	unsigned int GetSize();
	
	//ノートリスト取得：startTime, endTime はチックタイム
	int GetNoteList(SMNoteList* pNoteList);
	
	//ノートリスト取得：startTime, endTime はリアルタイム(msec)
	int GetNoteListWithRealTime(SMNoteList* pNoteList, unsigned int timeDivision);
	
	//コピー
	int CopyFrom(SMTrack* pSrcTrack);
	
private:
	
	//イベントデータ
	typedef struct {
		SMEvent::EventType type;
		unsigned char status;
		unsigned char meta;
		unsigned int size;
		unsigned char data[4];
	} SMEventData;
	
	//データセット
	typedef struct {
		unsigned int deltaTime;
		SMEventData eventData;
		unsigned char portNo;
	} SMDataSet;
	
	//拡張データマップ：インデックス→データ位置
	typedef std::map<unsigned int, unsigned char*> SMExDataMap;
	typedef std::pair<unsigned int, unsigned char*> SMExDataMapPair;
	
	//ノート情報マップ：ノート特定キー→ノートリストインデックス
	typedef std::map<unsigned int, unsigned int> SMNoteMap;
	typedef std::pair<unsigned int, unsigned int> SMNoteMapPair;
	
private:
	
	SMSimpleList m_List;
	SMExDataMap m_ExDataMap;
	
	unsigned int _GetNoteKey(unsigned char portNo, unsigned char chNo, unsigned char noteNo);
	int _GetNoteList(SMNoteList* pNoteList, unsigned int timeDivision);
	double _ConvTick2TimeMsec(unsigned int tickTime, unsigned int tempo, unsigned int timeDivision);
	
	//代入とコピーコンストラクタの禁止
	void operator=(const SMTrack&);
	SMTrack(const SMTrack&);

};

#pragma warning(default:4251)


