//=============================================================================
//! @file
//! @brief  Standard MIDI File (SMF) 読み取り
//! @author Yoshi.
//=============================================================================

#include "smf_loader.h"

#include <vector>
#include <map>
#include <algorithm>

#define _CRT_SECURE_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>

//-----------------------------------------------------------------------------
// 内部定義
//-----------------------------------------------------------------------------
namespace {

// 定数系定義

// GMリセットバイトシーケンス
const unsigned char DATA_GM1[] = {0xF0, 0x7E, 0x7F, 0x09, 0x01, 0xF7};
const unsigned char DATA_GM2[] = {0xF0, 0x7E, 0x7F, 0x09, 0x03, 0xF7};

// ヤマハ系リセットバイトシーケンス
const unsigned char DATA_XG[]  = {0xF0, 0x43, 0x10, 0x4C, 0x00, 0x00, 0x7E, 0x00, 0xF7};
const unsigned char DATA_MU0[] = {0xF0, 0x43, 0x10, 0x49, 0x00, 0x00, 0x12, 0x00, 0xF7};
const unsigned char DATA_MU1[] = {0xF0, 0x43, 0x10, 0x49, 0x00, 0x00, 0x12, 0x01, 0xF7};

// ローランド系リセットバイトシーケンス
const unsigned char DATA_GS[]  = {0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7F, 0x00, 0x41, 0xF7};
const unsigned char DATA_88S[] = {0xF0, 0x41, 0x10, 0x42, 0x12, 0x00, 0x00, 0x7F, 0x00, 0x01, 0xF7};
const unsigned char DATA_88D[] = {0xF0, 0x41, 0x10, 0x42, 0x12, 0x00, 0x00, 0x7F, 0x01, 0x00, 0xF7};

// マスターボリューム
const unsigned char DATA_VOL_GM[] = {0xF0, 0x7F, 0x7F, 0x04, 0x01};
const unsigned char DATA_VOL_GS[] = {0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x04};
const unsigned char DATA_VOL_XG[] = {0xF0, 0x43, 0x10, 0x4c, 0x00, 0x00, 0x04};


//-----------------------------------------------------------------------------
// エンディアン変換(16bit)
//-----------------------------------------------------------------------------
int Swap16(const unsigned char* value)
{
    return (static_cast<int>(value[1])     )
         | (static_cast<int>(value[0]) << 8);
}

//-----------------------------------------------------------------------------
// エンディアン変換(24bit)
//-----------------------------------------------------------------------------
int Swap24(const unsigned char* value)
{
    return (static_cast<int>(value[2])      )
         | (static_cast<int>(value[1]) <<  8)
         | (static_cast<int>(value[0]) << 16);
}

//-----------------------------------------------------------------------------
// エンディアン変換(32bit)
//-----------------------------------------------------------------------------
int Swap32(const unsigned char* value)
{
    return (static_cast<int>(value[3])      )
         | (static_cast<int>(value[2]) <<  8)
         | (static_cast<int>(value[1]) << 16)
         | (static_cast<int>(value[0]) << 24);
}

//-----------------------------------------------------------------------------
// 64bit割り算
//-----------------------------------------------------------------------------
inline int Mul64Div32(int a, int b, int c)
{
    return static_cast<int>(long long(a) * long long(b) / long long(c));
    //return MulDiv(a, b, c);
}

//-----------------------------------------------------------------------------
// ブランク文字列消し
//-----------------------------------------------------------------------------
template <int LEN>
void TrimBlank(char (&buf)[LEN])
{
    const char SPACE0 = char(0x81);
    const char SPACE1 = char(0x40);

    buf[LEN - 1] = '\0';

    for (int i = (LEN - 1); 0 < i; --i)
    {
        const char c0 = buf[i];
        const char c1 = buf[i - 1];

        // 半角スペース、タブ、改行、全角スペースの２バイト目以外なら、そのまま
        if (c0 != ' ' && c0 != '\t' && c0 != '\r' && c0 != '\n' && c0 != SPACE0)
        {
            break;
        }

        // 全角文字のうち、スペースは削除する
        if (c0 == SPACE0 && c1 == SPACE1)
        {
            buf[i--] = '\0';
        }

        buf[i] = '\0';
    }
}

} //namespace


//-----------------------------------------------------------------------------
// SMFデータ解析
//-----------------------------------------------------------------------------
class SmfParser
{
public:
    typedef std::vector<SmfLoader::MidiMessage> MidiMessageVector;
    typedef std::map<int, int>                  TempoMap;

public:
    SmfParser(const unsigned char* data, size_t size, const SmfLoader::LoadOption& option, int rate_);
    ~SmfParser();

    // 解析
    void ParseSmf();

    // MIDI演奏データアクセサ
    const MidiMessageVector& GetMidiMessageData() const { return messages_; }
    SmfLoader::ResetType GetResetType() const { return reset_type_; }
    SmfLoader::SmfFormat GetSmfFormat() const { return smf_format_; }
    int GetTrackNum() const { return track_num_; }
    int GetTimeBase() const { return time_base_; }
    __int64 GetDuration() const { return duration_; }
    int GetPortNum()  const { return port_num_; }
    // メタデータアクセサ
    //void GetTitle(char* title) const { memcpy(title, title_, sizeof(title_)); }
    //void GetCopyright(char* copyright) const { memcpy(copyright, copyright_, sizeof(copyright_)); }

private:
    bool ParseHeader(const unsigned char* data, int size, int& used);
    bool ParseTrack(const unsigned char* data, int size, int& used);

    int ParseExMessage(const unsigned char* data, int *sysex_type);
    int ParseMetaEvent(const unsigned char* data, int delta_time);
    __int64 CalcPlayTime(int delta_time) const;

    int ParseNumber(const unsigned char* data, int& used);
    int ParseMessage(const unsigned char* data, int& used, int prev_msg, bool& ignore);

public:
    const unsigned char*    raw_data_;      // MIDIの生データ
    int                     raw_size_;      // 生データサイズ
    SmfLoader::LoadOption   option_;        // 読み込みオプション

    // MIDI演奏データ
    MidiMessageVector       messages_;      // 再生時間・チャンネル順に並べたMIDIメッセージ
    TempoMap                tempo_map_;     // テンポリスト
    SmfLoader::ResetType    reset_type_;    // 音源リセットタイプ
    SmfLoader::SmfFormat    smf_format_;    // SMFフォーマット
    int                     track_num_;     // Format1のトラック数（0は1固定）
    int                     time_base_;     // タイムベース
    __int64                 duration_;      // ミリ秒単位の時間
    int                     port_num_;      // ポート数
    int                     rate_;
    // メタデータ
    //char  title_[SmfLoader::METATEXT_MAXLEN + 1];
    //char  copyright_[SmfLoader::METATEXT_MAXLEN + 1];
};


//-----------------------------------------------------------------------------
// コンストラクタ
//-----------------------------------------------------------------------------
SmfLoader::SmfLoader()
    : message_data_(NULL)
    , message_num_(0)
    , reset_type_(RESET_TYPE_GM1)
    , smf_format_(SMF_FORMAT_0)
    , track_num_(0)
    , time_base_(1)
    , duration_(0)
    , port_num_(1)
{
//  memset(title_, 0, sizeof(title_));
//  memset(copyright_, 0, sizeof(copyright_));
}

//-----------------------------------------------------------------------------
// デストラクタ
//-----------------------------------------------------------------------------
SmfLoader::~SmfLoader()
{
    Clear();
}

//-----------------------------------------------------------------------------
// SMFデータを読み込む
//-----------------------------------------------------------------------------
bool SmfLoader::Load(const void* data, size_t size, const LoadOption& option, int rate)
{
    Clear();
    SmfParser parser(static_cast<const unsigned char*>(data), size, option, rate);
    parser.ParseSmf();

    const SmfParser::MidiMessageVector& msg = parser.GetMidiMessageData();
    if (msg.empty())
    {
        return false;
    }

    message_num_ = msg.size();
    message_data_ = new MidiMessage[message_num_];
    if (!message_data_)
    {
        Clear();
        return false;
    }

    for (int i = 0; i < message_num_; ++i)
    {
        message_data_[i] = msg[i];
    }

    reset_type_ = parser.GetResetType();
    smf_format_ = parser.GetSmfFormat();
    track_num_ = parser.GetTrackNum();
    time_base_ = parser.GetTimeBase();
    duration_ = parser.GetDuration();
    port_num_ = parser.GetPortNum();
    //parser.GetTitle(title_);
    //parser.GetCopyright(copyright_);
    return true;
}

//-----------------------------------------------------------------------------
// 読み込んだデータをクリアする
//-----------------------------------------------------------------------------
void SmfLoader::Clear()
{
    delete [] message_data_;
    message_data_ = NULL;
    message_num_ = 0;

    reset_type_ = RESET_TYPE_GM1;
    smf_format_ = SMF_FORMAT_0;
    track_num_ = 0;
    time_base_ = 1;
    duration_ = 0;

    //memset(title_, 0, sizeof(title_));
    //memset(copyright_, 0, sizeof(copyright_));
}

//-----------------------------------------------------------------------------
// 再生するMIDIメッセージ数取得
//-----------------------------------------------------------------------------
int SmfLoader::GetMidiMessageNum() const
{
    return message_num_;
}

//-----------------------------------------------------------------------------
// 指定インデックスのMIDIメッセージ取得
//-----------------------------------------------------------------------------
const SmfLoader::MidiMessage& SmfLoader::GetMidiMessage(int index) const
{
    if (index < message_num_)
    {
        return message_data_[index];
    }

    static MidiMessage dummy_message;
    return dummy_message;
}

//-----------------------------------------------------------------------------
// 音源リセットメッセージ取得
//-----------------------------------------------------------------------------
const void* SmfLoader::GetResetMessageData() const
{
    const void* data = DATA_GM1;
    switch (reset_type_)
    {
    case RESET_TYPE_GM1: data = DATA_GM1; break;
    case RESET_TYPE_GM2: data = DATA_GM2; break;
    case RESET_TYPE_XG:  data = DATA_XG;  break;
    case RESET_TYPE_GS:  data = DATA_GS;  break;
    }

    return data;
}
const void* SmfLoader::GetResetMessageData(SmfLoader::ResetType type)
{
    const void* data = DATA_GM1;
    switch (type)
    {
    case RESET_TYPE_GM1: data = DATA_GM1; break;
    case RESET_TYPE_GM2: data = DATA_GM2; break;
    case RESET_TYPE_XG:  data = DATA_XG;  break;
    case RESET_TYPE_GS:  data = DATA_GS;  break;
    }
    return data;
}
//-----------------------------------------------------------------------------
// 音源リセットメッセージのバイト数取得
//-----------------------------------------------------------------------------
int SmfLoader::GetResetMessageSize() const
{
    int size = sizeof(DATA_GM1);
    switch (reset_type_)
    {
    case RESET_TYPE_GM1: size = sizeof(DATA_GM1); break;
    case RESET_TYPE_GM2: size = sizeof(DATA_GM2); break;
    case RESET_TYPE_XG:  size = sizeof(DATA_XG);  break;
    case RESET_TYPE_GS:  size = sizeof(DATA_GS);  break;
    }

    return size;
}
int SmfLoader::GetResetMessageSize(SmfLoader::ResetType type)
{
    int size = sizeof(DATA_GM1);
    switch (type)
    {
    case RESET_TYPE_GM1: size = sizeof(DATA_GM1); break;
    case RESET_TYPE_GM2: size = sizeof(DATA_GM2); break;
    case RESET_TYPE_XG:  size = sizeof(DATA_XG);  break;
    case RESET_TYPE_GS:  size = sizeof(DATA_GS);  break;
    }
    return size;
}
//-----------------------------------------------------------------------------
// 音源リセットタイプを取得
//-----------------------------------------------------------------------------
SmfLoader::ResetType SmfLoader::GetResetType() const
{
    return reset_type_;
}

//-----------------------------------------------------------------------------
// SMFフォーマット取得
//-----------------------------------------------------------------------------
SmfLoader::SmfFormat SmfLoader::GetSmfFormat() const
{
    return smf_format_;
}

//-----------------------------------------------------------------------------
// トラック数取得
//-----------------------------------------------------------------------------
int SmfLoader::GetTrackNum() const
{
    return track_num_;
}

//-----------------------------------------------------------------------------
// タイムベース（分解能）取得
//-----------------------------------------------------------------------------
int SmfLoader::GetTimeBase() const
{
    return time_base_;
}

//-----------------------------------------------------------------------------
// 曲の長さ取得
//-----------------------------------------------------------------------------
__int64 SmfLoader::GetDuration() const
{
    return duration_;
}

//-----------------------------------------------------------------------------
// ポート数取得
//-----------------------------------------------------------------------------
int SmfLoader::GetPortNum() const
{
    return port_num_;
}

//-----------------------------------------------------------------------------
// メタデータに設定されたタイトル取得
//-----------------------------------------------------------------------------
//const char* SmfLoader::GetTitle() const
//{
//  return title_;
//}

//-----------------------------------------------------------------------------
// メタデータに設定された権利情報取得
//-----------------------------------------------------------------------------
//const char* SmfLoader::GetCopyright() const
//{
//  return copyright_;
//}


//-----------------------------------------------------------------------------
// コンストラクタ
//-----------------------------------------------------------------------------
SmfParser::SmfParser(const unsigned char* data, size_t size, const SmfLoader::LoadOption& option, int rate)
    : raw_data_(data)
    , raw_size_(size)
    , option_(option)
    , reset_type_(SmfLoader::RESET_TYPE_GM1)
    , smf_format_(SmfLoader::SMF_FORMAT_0)
    , track_num_(0)
    , time_base_(1)
    , duration_(0)
    , port_num_(1)
    , rate_(rate)
{
    //memset(title_, 0, sizeof(title_));
    //memset(copyright_, 0, sizeof(copyright_));
    //ParseSmf();
}

//-----------------------------------------------------------------------------
// デストラクタ
//-----------------------------------------------------------------------------
SmfParser::~SmfParser()
{
}

//-----------------------------------------------------------------------------
// SMFデータを解析する
//-----------------------------------------------------------------------------
void SmfParser::ParseSmf()
{
    const unsigned char* data = raw_data_;
    int size = raw_size_;
    int used = 0;

    // ヘッダを解析する
    if (!ParseHeader(data, size, used))
    {
        return;
    }

    data += used;
    size -= used;

    for (int i = 0; (i < track_num_) && (0 < size); ++i)
    {
        used = 0;

        // 各トラックを解析する
        if (!ParseTrack(data, size, used))
        {
            return;
        }

        data += used;
        size -= used;
    }

    struct MessageSortFunctor
    {
        // 時間基準でソートする
        bool operator()( const SmfLoader::MidiMessage& lhs, const SmfLoader::MidiMessage& rhs) const
        {
            return (lhs.time_smp < rhs.time_smp);
        }
    };

    // 安定ソートにて、絶対時間順に並べる
    std::stable_sort(messages_.begin(), messages_.end(), MessageSortFunctor());
}

//-----------------------------------------------------------------------------
// MIDI/MThd解析
//-----------------------------------------------------------------------------
bool SmfParser::ParseHeader(const unsigned char* data, int size, int& used)
{
    // "MThd"確認
    if (data[0] != 'M' || data[1] != 'T' || data[2] != 'h' || data[3] != 'd')
    {
        return false;
    }

    data += 4;

    // ヘッダのサイズ分データが無い場合は、不正なデータとし、解析しない
    int header_size = static_cast<int>(Swap32(data));
    if (header_size < 6)
    {
        return false;
    }

    header_size -= 6;
    data += 4;

    smf_format_ = static_cast<SmfLoader::SmfFormat>(Swap16(data));
    data += 2;

    // SMFフォーマット0,1のみ対応（2は未対応）
    if ((smf_format_ != SmfLoader::SMF_FORMAT_0) && (smf_format_ != SmfLoader::SMF_FORMAT_1))
    {
        return false;
    }

    track_num_ = Swap16(data);
    data += 2;
    time_base_ = Swap16(data);

    // 追加のヘッダ領域を無視する
    used += (header_size + 14);

    // 初期テンポ設定
    tempo_map_.clear();
    tempo_map_[0] = 120;
    return true;
}

//-----------------------------------------------------------------------------
// MIDI/MTrk解析
//-----------------------------------------------------------------------------
bool SmfParser::ParseTrack(const unsigned char* data, int size, int& used)
{
    // "MTrk"確認
    if (data[0] != 'M' || data[1] != 'T' || data[2] != 'r' || data[3] != 'k')
    {
        return false;
    }

    data += 4;

    // トラックのサイズ分データが無い場合は、不正なデータとし、解析しない
    int track_size = static_cast<int>(Swap32(data));
    if (size < track_size)
    {
        return false;
    }

    data += 4;
    used += 8;

    int delta_time = 0, prev_message = 0, result = 0;
    int port_index = 0;
    // 演奏データを取得
    while (0 < track_size)
    {
        // デルタタイム取得
        delta_time += ParseNumber(data, result);
        if (track_size < result)
        {
            data += track_size;
            used += track_size;
            track_size = 0;
            return true;
        }

        track_size -= result;
        data += result;
        used += result;

        // システムエクスクルーシブを処理
        int sysex_type = 0;
        result = ParseExMessage(data, &sysex_type);
        if (0 < result)
        {
            __int64 play_time = CalcPlayTime(delta_time);
            int delta_size;
            int sysex_size = ParseNumber(&data[1], delta_size);
            if (sysex_size != 0)
            {
                SmfLoader::MidiMessage msg = //{play_time, message};
                { play_time, sysex_type, port_index };
                msg.sysex_dump.push_back(0xf0);
                if (data[0] == 0xf0) {
                    for (int i = 0; i < sysex_size; i++) {
                        msg.sysex_dump.push_back(data[i + 1 + delta_size]);
                    }
                }
                else {//f7
                    for (int i = 0; i < sysex_size-1; i++) {
                        msg.sysex_dump.push_back(data[i + 2 + delta_size]);
                    }
                }
                messages_.push_back(msg);

                prev_message = 0;
            }

            track_size -= result;
            data += result;
            used += result;
            continue;
        }

        // メタイベントを処理
        result = ParseMetaEvent(data, delta_time);
        // トラック終了検出（ここまで処理しないといけない）
        if (result == SmfLoader::END_OF_TRACK)
        {
            __int64 play_time = CalcPlayTime(delta_time);
            SmfLoader::MidiMessage msg = {play_time, SmfLoader::END_OF_TRACK, port_index};
            // 最後のメッセージを追加
            messages_.push_back(msg);

            // 曲長を更新
            if (duration_ < play_time)
            {
                duration_ = play_time;
            }

            track_size -= 3;
            data += 3;
            used += 3;
            return true;
        }
        else if (0 < result)
        {
            int event_type = data[1];
            if (event_type == 0x21) {
                port_index = data[3];
            }

            track_size -= result;
            data += result;
            used += result;
            continue;
        }

        result = 0;
        bool ignore = false;
        int message = ParseMessage(data, result, prev_message, ignore);

        track_size -= result;
        data += result;
        used += result;

        // 絶対時間を計算する
        __int64 play_time = CalcPlayTime(delta_time);
        SmfLoader::MidiMessage msg = {play_time, message, port_index };

        if (message != 0)
        {
            if (!ignore)
            {
                messages_.push_back(msg);
            }

            prev_message = message;
        }
    }

    return true;
}

//-----------------------------------------------------------------------------
// システムエクスクルーシブ解析
//-----------------------------------------------------------------------------
int SmfParser::ParseExMessage(const unsigned char* data, int *sysex_type)
{
    *sysex_type = 0;
    // システムエクスクルーシブでない場合は無視
    if (data[0] != 0xF0 && data[0] != 0xF7)
    {
        return 0;
    }
    int used;
    int sysex_size = ParseNumber(&data[1], used);
    // 音源リセットタイプを判定する
    if (option_.detect_reset_type)
    {
        struct ResetItem
        {
            const unsigned char*    reset_data;
            int                     reset_size;
            SmfLoader::ResetType    reset_type;
        };

        static const ResetItem reset_list[] =
        {
            { &DATA_GM1[1], sizeof(DATA_GM1) - 1, SmfLoader::RESET_TYPE_GM1 },
            { &DATA_GM2[1], sizeof(DATA_GM2) - 1, SmfLoader::RESET_TYPE_GM2 },
            { &DATA_XG [1], sizeof(DATA_XG ) - 1, SmfLoader::RESET_TYPE_XG  },
            { &DATA_MU0[1], sizeof(DATA_MU0) - 1, SmfLoader::RESET_TYPE_XG  },
            { &DATA_MU1[1], sizeof(DATA_MU1) - 1, SmfLoader::RESET_TYPE_XG  },
            { &DATA_GS [1], sizeof(DATA_GS ) - 1, SmfLoader::RESET_TYPE_GS  },
            { &DATA_88S[1], sizeof(DATA_88S) - 1, SmfLoader::RESET_TYPE_GS  },
            { &DATA_88D[1], sizeof(DATA_88D) - 1, SmfLoader::RESET_TYPE_GS  },
        };
        static const struct{
            const unsigned char* data;
            int size;
        }vol_list[] = {
            { &DATA_VOL_GM[1], sizeof(DATA_VOL_GM) - 1},
            { &DATA_VOL_GS[1], sizeof(DATA_VOL_GS) - 1},
            { &DATA_VOL_XG[1], sizeof(DATA_VOL_XG) - 1},
        };
        for (int i = 0; i < (sizeof(reset_list) / sizeof(reset_list[0])); ++i)
        {
            if (reset_list[i].reset_size == sysex_size)
            {
                if (memcmp(&data[2], reset_list[i].reset_data, sysex_size) == 0)
                {
                    reset_type_ = reset_list[i].reset_type;
                    *sysex_type = SmfLoader::SYS_EX_ALL_PORT;
                    break;
                }
            }
        }
        if(*sysex_type == 0){
            for (int i = 0; i < _countof(vol_list); ++i){
                if (vol_list[i].size < sysex_size)
                {
                    if (memcmp(&data[2], vol_list[i].data, vol_list[i].size) == 0){
                        *sysex_type = SmfLoader::SYS_EX_ALL_PORT;
                        break;
                    }
                }
            }
        }
    }
    if(*sysex_type == 0){
        *sysex_type = SmfLoader::SYS_EX;
    }
    return int((data[0] == 0xF0)? 2 : 1) + sysex_size + (used -1);
}

//-----------------------------------------------------------------------------
// メタイベントなど、演奏に関係ないデータを解析
//-----------------------------------------------------------------------------
int SmfParser::ParseMetaEvent(const unsigned char* data, int delta_time)
{
    if (data[0] != 0xFF)
    {
        return 0;
    }

    int event_type = data[1];

    // エンドオブトラックの場合は、-1を返す
    if (event_type == 0x2F)
    {
        return SmfLoader::END_OF_TRACK;
    }

    int used = 0;
    int event_size = ParseNumber(&data[2], used);

    switch (event_type)
    {/*
    case 0x01:  // テキストイベント
    case 0x03:  // シーケンス名／トラック名
        if (title_[0] == '\0')
        {
            int copy_size = std::min<int>(event_size, sizeof(title_) - 1);
            memcpy(title_, &data[used + 2], copy_size);
            TrimBlank(title_);
        }
        break;

    case 0x02:  // 著作者
        if (copyright_[0] == '\0')
        {
            int copy_size = std::min<int>(event_size, sizeof(copyright_) - 1);
            memcpy(copyright_, &data[used + 2], copy_size);
            TrimBlank(copyright_);
        }
        break;
        */
    case 0x51:  // テンポ変更
        {
            int tttttt = Swap24(&data[used + 2]);
            int tempo = Mul64Div32(60, 1000000, tttttt);
            tempo_map_[delta_time] = tempo;
        }
        break;
    case 0x21:  // ポート
        {
            int port_index = data[used + 2];
            if (port_num_ <= port_index) {
                port_num_ = port_index + 1;
            }
        }
        break;
/*  case 0x04:  // 楽器名
    case 0x05:  // 歌詞
    case 0x06:  // マーカー
        break;
*/
    default:
        break;
    }

    // サイズのバイト数、データのバイト数、先頭２バイトの合計を返す
    return (event_size + used + 2);
}

//-----------------------------------------------------------------------------
// 現在のデルタタイムに対する絶対的な再生時間を計算する
//-----------------------------------------------------------------------------
__int64 SmfParser::CalcPlayTime(int delta_time) const
{
    int /*play_time = 0, */dtime = 0, ptime = 0, tempo = 0;
    double play_time = 0;
    for (TempoMap::const_iterator it = tempo_map_.begin(); it != tempo_map_.end(); ++it)
    {
        // デルタタイムが過ぎている場合は、ループを抜ける
        if (delta_time < it->first)
        {
            break;
        }

        dtime = it->first - ptime;
        if (0 < dtime)
        {
            //play_time += Mul64Div32(dtime, 60 * 1000, tempo * time_base_);
            play_time += dtime * 60.0 / (tempo*time_base_);
        }

        ptime = it->first;
        tempo = it->second;
    }

    dtime = delta_time - ptime;
    //play_time += Mul64Div32(dtime, 60 * 1000, tempo * time_base_);
    play_time += dtime * 60.0 / (tempo*time_base_);
    return (__int64)(play_time * rate_);
    //return play_time;
}

//-----------------------------------------------------------------------------
// 可変長表現で示される数値を取得する
//-----------------------------------------------------------------------------
int SmfParser::ParseNumber(const unsigned char* data, int& used)
{
    int value = 0;
    used = 0;

    for (int i = 0; i < 4; ++i)
    {
        value <<= 7;
        value |= int(data[i] & 0x7F);
        ++used;

        if (!(data[i] & 0x80))
        {
            break;
        }
    }

    return value;
}

//-----------------------------------------------------------------------------
// MIDIメッセージを取得する
//-----------------------------------------------------------------------------
int SmfParser::ParseMessage(const unsigned char* data, int& used, int prev_message, bool& ignore)
{
    unsigned char temp = data[0];

    // ランニングステータス対応
    if ((temp & 0x80) == 0)
    {
        temp = (prev_message & 0xFF);
        used = 0;
    }
    else
    {
        used = 1;
    }

    int message = temp;

    switch (temp & 0xF0)
    {
    default:
        message = 0;
        break;

    case 0x80:  // ノートＯＮ
    case 0x90:  // ノートＯＦＦ
    case 0xA0:  // ポリフォニックキープレッシャー
    case 0xB0:  // コントロールチェンジ
    case 0xE0:  // ピッチベンドチェンジ
        message |= ((int(data[used]) << 8) | (int(data[used + 1]) << 16));
        used += 2;
        break;

    case 0xC0:  // プログラムチェンジ
    case 0xD0:  // チャネルプレッシャー
        message |= (int(data[used]) << 8);
        used += 1;
        break;
    }

    // バンクセレクトを無視(0x00:bank select MSB/0x20:bank select LSB)
    if (option_.ignore_bank_select)
    {
        int type = (message & 0xF0);
        int mval = ((message >> 8) & 0xFF);

        if ((type == 0xB0) && ((mval == 0x00) || (mval == 0x20)))
        {
            ignore = true;
        }
    }

    return message;
}
