//ms修正 static void MstimeFix(ref List <Bfr_NoteData> b_noteL, ref List <Bfr_TempData> b_tmpL) { var beforTempList = new List <Bfr_TempData>(b_tmpL); //変更前の値を保存 //--テンポのmsTime修正-- for (int i = 1; i < b_tmpL.Count; i++) { Bfr_TempData tempData = b_tmpL[i]; //現在対象のデータ float timeDiff = tempData.tickTime - b_tmpL[i - 1].tickTime; tempData.msTime = timeDiff * b_tmpL[i - 1].tick + b_tmpL[i - 1].msTime; b_tmpL[i] = tempData; } //--ノーツのmsTime修正-- for (int i = 0; i < b_noteL.Count; i++) { for (int j = b_tmpL.Count - 1; j >= 0; j--) { if (b_noteL[i].tickTime >= b_tmpL[j].tickTime) //テンポ変更した後 { Bfr_NoteData note = b_noteL[i]; float timeDifference = b_noteL[i].tickTime - b_tmpL[j].tickTime; note.msTime = timeDifference * b_tmpL[j].tick + b_tmpL[j].msTime; // 計算後のテンポ変更イベント時間+そこからの自分の時間 b_noteL[i] = note; break; } } } }
//トラック演奏データ解析 static void TrackMusicAnaly(byte[] data, HeaderChunkData header, ref List <Bfr_NoteData> b_noteL, ref List <Bfr_TempData> b_tmpL) { //トラック内で引き継ぎたいもの uint tickTime = 0; //開始からのTick数 byte statusByte = 0; //FFとか入る uint Instrument = 0; //楽器 //データ分 for (int i = 0; i < data.Length;) { //---デルタタイム--- tickTime += DeltaMath(data, ref i); //---ランニングステータス--- if (data[i] < 0x80) { //*** } else { statusByte = data[i++]; } //---ステータスバイト--- //ステバ分岐 この辺はもう筋肉 //--Midiイベント-- if (statusByte >= 0x80 & statusByte <= 0xef) { switch (statusByte & 0xf0) { case 0x90: //ノートオン { byte leanNum = data[i++]; //音階 byte velocity = data[i++]; //音の強さ //ノート情報まとめる Bfr_NoteData noteData = new Bfr_NoteData(); noteData.tickTime = (int)tickTime; noteData.msTime = 0; //後でやる noteData.leanNum = (int)leanNum; noteData.ch = statusByte & 0x0f; //下4を取得 //ベロ値でオンオフを送ってくる奴に対応 if (velocity > 0) //音が鳴っていたらオン { noteData.type = NoteType.ON; } else { noteData.type = NoteType.OFF; } b_noteL.Add(noteData); } break; case 0x80: //ノートオフ { byte leanNum = data[i++]; byte velocity = data[i++]; Bfr_NoteData noteData = new Bfr_NoteData(); noteData.tickTime = (int)tickTime; noteData.msTime = 0; noteData.leanNum = (int)leanNum; noteData.ch = statusByte & 0x0f; //下4を取得 noteData.type = NoteType.OFF; //オフしか来ない b_noteL.Add(noteData); } break; case 0xc0: //プログラムチェンジ 音色 楽器を変える Instrument = data[i++]; break; case 0xa0: //キープッシャー i += 2; break; case 0xb0: //コンチェ i += 2; break; case 0xd0: //チェンネルプレッシャー i += 1; break; case 0xe0: //ピッチベンド i += 2; break; } } //--システムエクスクルーシブイベント-- else if (statusByte == 0x70 || statusByte == 0x7f) { byte dataLen = data[i++]; i += dataLen; } //--メタイベ-- else if (statusByte == 0xff) { byte eveNum = data[i++]; byte dataLen = (byte)DeltaMath(data, ref i); //可変長 switch (eveNum) { case 0x51: { Bfr_TempData tempData = new Bfr_TempData(); tempData.tickTime = (int)tickTime; tempData.msTime = 0; //後でやる //3byte固定 4分音符の長さをマイクロ秒で uint temp = 0; temp |= data[i++]; temp <<= 8; temp |= data[i++]; temp <<= 8; temp |= data[i++]; //BPM計算 = 60秒のマクロ秒/4分音符のマイクロ秒 tempData.bpm = SECOND_BASE * 1000000 / (float)temp; //小数点第1位切り捨て tempData.bpm = (float)Math.Floor(tempData.bpm * 10) / 10; //tick値=60/分解能*1000 tempData.tick = (SECOND_BASE / tempData.bpm / header.timeBase * 1000); b_tmpL.Add(tempData); } break; default: i += dataLen; //メタはデータ長で全てとばせる 書くの面倒だった break; } } } }