Exemple #1
0
        protected override object AddNewCore()
        {
            ITempoData data1 = new TempoData();

            base.Add(data1);
            return(data1);
        }
Exemple #2
0
    void ModificationEventTimes()
    {
        // 一時格納用(計算前の時間を保持したいため)
        var tempTempoList = new List <TempoData>(tempoList);

        // テンポイベント時間修正
        for (int i = 1; i < tempoList.Count; i++)
        {
            TempoData tempo = tempoList[i];

            int timeDifference = tempTempoList[i].eventTime - tempTempoList[i - 1].eventTime;
            tempo.eventTime = (int)(timeDifference * tempoList[i - 1].tick) + tempoList[i - 1].eventTime;

            tempoList[i] = tempo;
        }

        // ノーツイベント時間修正
        for (int i = 0; i < noteList.Count; i++)
        {
            for (int j = tempoList.Count - 1; j >= 0; j--)
            {
                if (noteList[i].eventTime >= tempTempoList[j].eventTime)
                {
                    NoteData note = noteList[i];

                    int timeDifference = noteList[i].eventTime - tempTempoList[j].eventTime;
                    note.eventTime = (int)(timeDifference * tempTempoList[j].tick) + tempoList[j].eventTime;   // 計算後のテンポ変更イベント時間+その時間
                    noteList[i]    = note;
                    break;
                }
            }
        }
        // Debug.Log("FinEventTIme");
    }
Exemple #3
0
        protected override object AddNewCore()
        {
            ITempoData tempoData = new TempoData();

            Add(tempoData);

            // Not necessary to hook up event handlers, base class calls InsertItem

            return(tempoData);
        }
Exemple #4
0
 public void EvaluateCues(List <Cue> cues, List <TempoData> tempoData)
 {
     this.length = TempoData.TickToMilliseconds(cues[cues.Count - 1].tick, tempoData) - TempoData.TickToMilliseconds(cues[0].tick, tempoData);
     if (cues.Count >= 15 && this.length > 30000f)
     {
         SplitCues(cues);
         CalculateSpacing();
         CalculateDensity();
         CalculateReadability();
         difficultyRating = ((spacing + readability) / length) * 500f + (length / 100000f * lengthMultiplier);
     }
     else
     {
         difficultyRating = 0f;
     }
 }
Exemple #5
0
    void TrackDataAnalys(byte[] data, HeaderChunkData headerCH)
    {
        // Debug.Log(data.Length);
        uint CrTime     = 0;               // 現在の時間 [ ms ]
        byte statusByte = 0;               // ステータスバイト

        bool[] longFlags = new bool[128];  // ロングノーツ用フラグ

        for (int i = 0; i < data.Length;)
        {
            // Debug.Log(i);

            bool Fintrack  = false;
            uint deltaTime = 0;

            while (true)
            {
                var tmp = data[i++];

                // 下位7bitを格納
                deltaTime |= (tmp & (uint)0x7f);

                // 最上位1bitが0ならデータ終了
                if ((tmp & 0x80) == 0)
                {
                    break;
                }

                // 次の下位7bit用にビット移動
                deltaTime = deltaTime << 7;
            }

            // 現在の時間にデルタタイムを足す
            CrTime += deltaTime;

            /* ランニングステータスチェック */
            if (data[i] >= 0x80)
            {
                statusByte = data[i++]; // ステータスバイト保存
            }
            //else:ランニングステータス適応(前回のステータスバイトを使いまわす)

            // ステータスバイト後のデータ保存用
            byte dataByte0, dataByte1;
            // byte dataByte2, dataByte3;
            if (statusByte >= 0x80 && statusByte <= 0xef)
            {
                switch (statusByte & 0xf0)
                {
                /* チャンネルメッセージ */
                // ノートオフ
                case 0x80:
                    dataByte0 = data[i++];    // どのキーが離されたか
                    // ベロシティ値
                    dataByte1 = data[i++];

                    // 前のレーンがロングノーツなら
                    if (longFlags[dataByte0])
                    {
                        // ロング終点ノート情報生成
                        var note = new NoteData();
                        note.eventTime = (int)CrTime;
                        note.laneIndex = (int)dataByte0;
                        note.type      = NoteType.LongEnd;

                        // リストにつっこむ
                        noteList.Add(note);

                        // ロングノーツフラグ解除
                        longFlags[note.laneIndex] = false;
                    }
                    break;

                case 0x90:      // ノートオン(ノートオフが呼ばれるまでは押しっぱなし扱い)
                    // どのキーが押されたか
                    dataByte0 = data[i++];
                    // ベロシティ値という名の音の強さ。ノートオフメッセージの代わりにここで0を送ってくるタイプもある
                    dataByte1 = data[i++];

                    {
                        // ノート情報生成
                        var note = new NoteData();
                        note.eventTime = (int)CrTime;
                        note.laneIndex = (int)dataByte0;
                        note.type      = NoteType.Normal;
                        // 独自でやっている。ベロシティ値が最大のときのみロングの始点とする
                        if (dataByte1 == 127)
                        {
                            note.type = NoteType.LongStart;
                            // ロングノーツフラグセット
                            longFlags[note.laneIndex] = true;
                        }
                        // ノートオフイベントではなく、ベロシティ値0をノートオフとして保存する形式もあるので対応
                        if (dataByte1 == 0)
                        {
                            // 同じレーンで前回がロングノーツ始点なら
                            if (longFlags[note.laneIndex])
                            {
                                note.type = NoteType.LongEnd;
                                // ロングノーツフラグ解除
                                longFlags[note.laneIndex] = false;
                            }
                        }

                        // リストにつっこむ
                        noteList.Add(note);
                    }
                    break;

                case 0xa0:          // ポリフォニック キープレッシャー(鍵盤楽器で、キーを押した状態でさらに押し込んだ際に、その圧力に応じて送信される)
                    i += 2;         // 使わないのでスルー
                    break;

                case 0xb0:          // コントロールチェンジ(音量、音質など様々な要素を制御するための命令)
                    // コントロールする番号
                    dataByte0 = data[i++];
                    // 設定する値
                    dataByte1 = data[i++];

                    // ※0x00-0x77までがコントロールチェンジで、それ以上はチャンネルモードメッセージとして処理する
                    if (dataByte0 < 0x78)
                    {
                        // コントロールチェンジ
                    }
                    else
                    {
                        // チャンネルモードメッセージは一律データバイトを2つ使用している
                        // チャンネルモードメッセージ
                        switch (dataByte0)
                        {
                        case 0x78:              // オールサウンドオフ
                            // 該当するチャンネルの発音中の音を直ちに消音する。後述のオールノートオフより強制力が強い。
                            break;

                        case 0x79:              // リセットオールコントローラ
                            // 該当するチャンネルの全種類のコントロール値を初期化する。
                            break;

                        case 0x7a:              // ローカルコントロール
                            // オフ:鍵盤を弾くとMIDIメッセージは送信されるがピアノ自体から音は出ない
                            // オン:鍵盤を弾くと音源から音が出る(基本こっち)
                            break;

                        case 0x7b:              // オールノートオフ
                            // 該当するチャンネルの発音中の音すべてに対してノートオフ命令を出す
                            break;

                        /* MIDIモード設定 */
                        // オムニのオン・オフとモノ・ポリモードを組み合わせて4種類のモードがある
                        case 0x7c:              // オムニモードオフ
                            break;

                        case 0x7d:              // オムニモードオン
                            break;

                        case 0x7e:              // モノモードオン
                            break;

                        case 0x7f:              // モノモードオン
                            break;
                        }
                    }
                    break;

                case 0xc0:          // プログラムチェンジ(音色を変える命令)
                    i += 1;
                    break;

                case 0xd0:          // チャンネルプレッシャー(概ねポリフォニック キープレッシャーと同じだが、違いはそのチャンネルの全ノートナンバーに対して有効となる)
                    i += 1;
                    break;

                case 0xe0:          // ピッチベンド(ウォェーンウェューンの表現で使う)
                    i += 2;
                    // ボルテのつまみみたいなのを実装する場合、ここの値が役立つかも
                    break;
                }
            }

            /* システムエクスクルーシブ (SysEx) イベント*/
            else if (statusByte == 0x70 || statusByte == 0x7f)
            {
                byte dataLength = data[i++];
                i += dataLength;
            }

            /* メタイベント*/
            else if (statusByte == 0xff)
            {
                // メタイベントの番号
                byte metaEventID = data[i++];
                // データ長
                byte dataLength = data[i++];

                switch (metaEventID)
                {
                case 0x00:          // シーケンスメッセージ
                    i += dataLength;
                    break;

                case 0x01:          // テキストイベント
                    i += dataLength;
                    break;

                case 0x02:          // 著作権表示
                    i += dataLength;
                    break;

                case 0x03:          // シーケンス/トラック名
                    i += dataLength;
                    break;

                case 0x04:          // 楽器名
                    i += dataLength;
                    break;

                case 0x05:          // 歌詞
                    i += dataLength;
                    break;

                case 0x06:          // マーカー
                    i += dataLength;
                    break;

                case 0x07:          // キューポイント
                    i += dataLength;
                    break;

                case 0x20:          // MIDIチャンネルプリフィクス
                    i += dataLength;
                    break;

                case 0x21:          // MIDIポートプリフィックス
                    i += dataLength;
                    break;

                case 0x2f:          // トラック終了
                    i       += dataLength;
                    Fintrack = true;
                    // ここでループを抜けても良い
                    break;

                case 0x51:          // テンポ変更
                {
                    // テンポ変更情報リストに格納する
                    var tempoData = new TempoData();
                    tempoData.eventTime = (int)CrTime;

                    // 4分音符の長さをマイクロ秒単位で格納されている
                    uint tempo = 0;
                    tempo  |= data[i++];
                    tempo <<= 8;
                    tempo  |= data[i++];
                    tempo <<= 8;
                    tempo  |= data[i++];

                    // BPM割り出し
                    tempoData.bpm = 60000000 / (float)tempo;

                    // 小数点第1で切り捨て処理(10にすると第一位、100にすると第2位まで切り捨てられる)
                    tempoData.bpm = Mathf.Floor(tempoData.bpm * 10) / 10;

                    // tick値割り出し
                    tempoData.tick = (60 / tempoData.bpm / headerCH.division * 1000);

                    // リストにつっこむ
                    tempoList.Add(tempoData);
                }
                break;

                case 0x54:          // SMTPEオフセット
                    i += dataLength;
                    break;

                case 0x58:          // 拍子
                    i += dataLength;
                    // 小節線を表示させるなら使えるかも
                    break;

                case 0x59:          // 調号
                    i += dataLength;
                    break;

                case 0x7f:          // シーケンサ固有メタイベント
                    i += dataLength;
                    break;
                }
            }

            if (Fintrack)
            {
                break;
            }
        }
        // Debug.Log("FinAnalyz");
    }
Exemple #6
0
        //midi / メタ イベント抽出用メソッド
        //主にデルタタイム、ノート番号、テンポの変化を見て配列に格納する
        private void TrackDataAnalaysis(byte[] data)
        {
            uint currentTime = 0;
            byte statusByte  = 0;

            bool[] longFlags = new bool[128];

            for (int i = 0; i < data.Length;)
            {
                uint deltaTime = 0;
                while (true)
                {
                    //デルタタイムの抽出
                    byte tmp = data[i++];
                    deltaTime |= tmp & (uint)0x7f;
                    if ((tmp & 0x80) == 0)
                    {
                        break;
                    }
                    deltaTime = deltaTime << 7;
                }
                currentTime = deltaTime;
                if (data[i] < 0x80)
                {
                    //ランニングステータス
                }
                else
                {
                    statusByte = data[i++];
                }

                byte dataByte0, dataByte1;

                if (statusByte >= 0x80 && statusByte <= 0xef)
                {
                    switch (statusByte & 0xf0)
                    {
                    //ノートオフ
                    case 0x80:
                        dataByte0 = data[i++];
                        dataByte1 = data[i++];
                        if (longFlags[dataByte0])
                        {
                            NoteData note = new NoteData();
                            note.eventTime = (int)currentTime;
                            note.laneIndex = (int)dataByte0;
                            note.type      = NoteType.Off;

                            if (harmony == 0x00)
                            {
                                PianoNoteList.Add(note);
                            }
                            else if (harmony == 0x1D || harmony == 0x1E)
                            {
                                GuitarNoteList.Add(note);
                            }
                            longFlags[note.laneIndex] = false;
                        }
                        break;

                    //ノートオン
                    case 0x90:
                        dataByte0 = data[i++];
                        dataByte1 = data[i++];
                        {
                            NoteData note = new NoteData();
                            note.eventTime            = (int)currentTime;
                            note.laneIndex            = (int)dataByte0;
                            note.type                 = NoteType.On;
                            longFlags[note.laneIndex] = true;
                            if (dataByte1 == 0)
                            {
                                if (longFlags[note.laneIndex])
                                {
                                    note.type = NoteType.Off;
                                    longFlags[note.laneIndex] = false;
                                }
                            }
                            if (harmony == 0x00)
                            {
                                PianoNoteList.Add(note);
                            }
                            else if (harmony == 0x1D || harmony == 0x1E)
                            {
                                GuitarNoteList.Add(note);
                            }
                        }
                        break;

                    //これ以降はインクリメント用
                    case 0xa0:
                        i += 2;
                        break;

                    case 0xb0:
                        dataByte0 = data[i++];
                        dataByte1 = data[i++];
                        if (dataByte0 < 0x78)
                        {
                        }
                        else
                        {
                            switch (dataByte0)
                            {
                            case 0x78:
                            case 0x7a:
                            case 0x7b:
                            case 0x7c:
                            case 0x7d:
                            case 0x7e:
                            case 0x7f:
                                break;
                            }
                        }
                        break;

                    case 0xc0:
                        dataByte0 = data[i++];
                        harmony   = dataByte0;
                        break;

                    case 0xd0:
                        i += 1;
                        break;

                    case 0xe0:
                        i += 2;
                        break;
                    }
                }
                //SysExイベント用、インクリメントオンリー
                else if (statusByte == 0x70 || statusByte == 0x7f)
                {
                    byte dataLength = data[i++];
                    i += dataLength;
                }
                //メタイベント用
                else if (statusByte == 0xff)
                {
                    byte metaEventID = data[i++];
                    byte dataLength  = data[i++];
                    switch (metaEventID)
                    {
                    case 0x00:
                    case 0x01:
                    case 0x02:
                    case 0x03:
                    case 0x04:
                    case 0x05:
                    case 0x06:
                    case 0x07:
                    case 0x20:
                    case 0x21:
                    case 0x2f:
                    case 0x54:
                    case 0x58:
                    case 0x59:
                    case 0x7f:
                        i += dataLength;
                        break;

                    //テンポ情報を格納
                    case 0x51:
                    {
                        TempoData tempoData = new TempoData();
                        tempoData.eventTime = (int)currentTime;
                        uint tempo = 0;
                        tempo        |= data[i++];
                        tempo       <<= 8;
                        tempo        |= data[i++];
                        tempo       <<= 8;
                        tempo        |= data[i++];
                        tempoData.bpm = 60000000 / (float)tempo;
                        tempoData.bpm = (float)(Math.Floor(tempoData.bpm * 10) / 10);
                        tempoList.Add(tempoData);
                    }
                    break;
                    }
                }
            }
        }
Exemple #7
0
    void TrackDataAnalys(byte[] data, HeaderChunkData headerCH)
    {
        // Debug.Log(data.Length);
        uint CrTime     = 0;
        byte statusByte = 0;

        bool[] longFlags = new bool[128];

        for (int i = 0; i < data.Length;)
        {
            // Debug.Log(i);

            bool Fintrack  = false;
            uint deltaTime = 0;

            while (true)
            {
                var tmp = data[i++];
                deltaTime |= (tmp & (uint)0x7f);
                if ((tmp & 0x80) == 0)
                {
                    break;
                }
                deltaTime = deltaTime << 7;
            }

            // 現在の時間にデルタタイムを足す
            CrTime += deltaTime;
            if (data[i] >= 0x80)
            {
                statusByte = data[i++];
            }
            //else:ランニングステータス適応(前回のステータスバイトを使いまわす)

            // ステータスバイト後のデータ保存用
            byte dataByte0, dataByte1;
            // byte dataByte2, dataByte3;
            if (statusByte >= 0x80 && statusByte <= 0xef)
            {
                switch (statusByte & 0xf0)
                {
                /* チャンネルメッセージ */
                // ノートオフ
                case 0x80:
                    dataByte0 = data[i++];
                    dataByte1 = data[i++];
                    if (longFlags[dataByte0])
                    {
                        var note = new NoteData();
                        note.eventTime = (int)CrTime;
                        note.laneIndex = (int)dataByte0;
                        note.type      = NoteType.LongEnd;

                        // リストにつっこむ
                        noteList.Add(note);

                        longFlags[note.laneIndex] = false;
                    }
                    break;

                // ノートオン(ノートオフが呼ばれるまでは押しっぱなし扱い)
                case 0x90:
                    // どのキーが押されたか
                    dataByte0 = data[i++];
                    dataByte1 = data[i++];

                    {
                        // ノート情報生成
                        var note = new NoteData();
                        note.eventTime = (int)CrTime;
                        note.laneIndex = (int)dataByte0;
                        note.type      = NoteType.Normal;
                        if (dataByte1 == 127)
                        {
                            note.type = NoteType.LongStart;
                            longFlags[note.laneIndex] = true;
                        }
                        // ノートオフイベントではなく、ベロシティ値0をノートオフとして保存する形式もあるので対応
                        if (dataByte1 == 0)
                        {
                            // 同じレーンで前回がロングノーツ始点なら
                            if (longFlags[note.laneIndex])
                            {
                                note.type = NoteType.LongEnd;
                                longFlags[note.laneIndex] = false;
                            }
                        }

                        // リストにつっこむ
                        noteList.Add(note);
                    }
                    break;

                case 0xa0:
                    i += 2;         // 使わないのでスルー
                    break;

                case 0xb0:
                    dataByte0 = data[i++];
                    dataByte1 = data[i++];

                    // ※0x00-0x77までがコントロールチェンジで、それ以上はチャンネルモードメッセージとして処理する
                    if (dataByte0 < 0x78)
                    {
                        // コントロールチェンジ
                    }
                    else
                    {
                        switch (dataByte0)
                        {
                        case 0x78:
                            break;

                        case 0x79:
                            break;

                        case 0x7a:
                            break;

                        case 0x7b:
                            break;

                        // オムニモードオフ
                        case 0x7c:
                            break;

                        // オムニモードオン
                        case 0x7d:
                            break;

                        // モノモードオン
                        case 0x7e:
                            break;

                        // モノモードオン
                        case 0x7f:
                            break;
                        }
                    }
                    break;

                case 0xc0:
                    i += 1;
                    break;

                case 0xd0:
                    i += 1;
                    break;

                case 0xe0:
                    i += 2;
                    break;
                }
            }

            else if (statusByte == 0x70 || statusByte == 0x7f)
            {
                byte dataLength = data[i++];
                i += dataLength;
            }

            else if (statusByte == 0xff)
            {
                           // メタイベント
                byte metaEventID = data[i++];
                byte dataLength  = data[i++];

                switch (metaEventID)
                {
                // シーケンスメッセージ
                case 0x00:
                    i += dataLength;
                    break;

                // テキストイベント
                case 0x01:
                    i += dataLength;
                    break;

                // 著作権表示
                case 0x02:
                    i += dataLength;
                    break;

                // シーケンス/トラック名
                case 0x03:
                    i += dataLength;
                    break;

                // 楽器名
                case 0x04:
                    i += dataLength;
                    break;

                // 歌詞
                case 0x05:
                    i += dataLength;
                    break;

                // マーカー
                case 0x06:
                    i += dataLength;
                    break;

                // キューポイント
                case 0x07:
                    i += dataLength;
                    break;

                // MIDIチャンネルプリフィクス
                case 0x20:
                    i += dataLength;
                    break;

                // MIDIポートプリフィックス
                case 0x21:
                    i += dataLength;
                    break;

                // トラック終了
                case 0x2f:
                    i       += dataLength;
                    Fintrack = true;
                    // ここでループを抜ける
                    break;

                // テンポ変更
                case 0x51:
                {
                    // テンポ変更情報リストに格納する
                    var tempoData = new TempoData();
                    tempoData.eventTime = (int)CrTime;

                    // 4分音符の長さをマイクロ秒単位で格納されている
                    uint tempo = 0;
                    tempo  |= data[i++];
                    tempo <<= 8;
                    tempo  |= data[i++];
                    tempo <<= 8;
                    tempo  |= data[i++];

                    // BPM割り出し
                    tempoData.bpm = 60000000 / (float)tempo;

                    // 小数点第1で切り捨て処理(10にすると第一位、100にすると第2位まで切り捨てられる)
                    tempoData.bpm = Mathf.Floor(tempoData.bpm * 10) / 10;

                    // tick値割り出し
                    tempoData.tick = (60 / tempoData.bpm / headerCH.division * 1000);

                    // リストにつっこむ
                    tempoList.Add(tempoData);
                }
                break;

                // SMTPEオフセット
                case 0x54:
                    i += dataLength;
                    break;

                // 拍子
                case 0x58:
                          // 小節線を表示させるなら使えるかも
                        i += dataLength;
                    break;

                // 調号
                case 0x59:
                    i += dataLength;
                    break;

                // シーケンサ固有メタイベント
                case 0x7f:
                    i += dataLength;
                    break;
                }
            }

            if (Fintrack)
            {
                break;
            }
        }
        // Debug.Log("FinAnalyz");
    }