public Int32 LoadChunkData(byte[] data, Int32 p) { int P = p; DataSize = Midi.readMSB32(data, P); P += 4; Console.WriteLine("HeaderSize : " + DataSize); MidiType = Midi.readMSB16(data, P); P += 2; Tracks = Midi.readMSB16(data, P); P += 2; Division = Midi.readMSB16(data, P); P += 2; Console.WriteLine("Midi Format : " + this.MidiType); Console.WriteLine("Traks : " + this.Tracks); if ((Division & 0x8000) == 0) { Console.WriteLine("Division : " + this.Division); } else { Smpte_fps = (Int16)(Division >> 8); Smpte_tpf = (Int16)(Division & 0x00ff); Console.WriteLine("SMPTE FPS : " + this.Smpte_fps); Console.WriteLine("SMPTE TPF : " + this.Smpte_tpf); } return(DataSize + 4); }
public byte[] toDJZ20() { ////文件结构 ////*文件开始*// //u32 FileSize ; //文件大小 //u32 EndTime ; //结束时间 //u32 NoteCount ; //音符数量 //Note* Notes ; //音符数据 //u32 MetaCount ; //控制数量 //Meta* Controls ; //控制数据 ////*文件结束*// ////文件字节流按照 高位存高字节 低位存低字节的顺序 ////音符结构体 (就是游戏中落下的块) //typedef struct { //u32 Time ; //时间 单位 ms , 该音符在什么时间激发 //u8 Line ; //游戏中的轨道:将由编辑器编辑 //u8 Data ; //发音 (就是MIDI事件的发音) //}Note; ////控制结构体 (就是游戏中落下的块) //typedef struct { //u32 Time ; //时间 单位 ms , 在什么时间激发 //u8 Type ; //类型 //u32 Data ; //数据 //}Meta; EventComparerDJZTime ec = new EventComparerDJZTime(); Events.Sort(ec); Controls.Sort(ec); Int32 FileSize = 4 + 4 + 4 + Events.Count * 6 + 4 + Controls.Count * 9; byte[] data = new byte[FileSize]; int P = 0; Midi.write32(data, P, (Int32)FileSize); P += 4; //文件大小 Midi.write32(data, P, (Int32)EndTime); P += 4; //结束时间 Midi.write32(data, P, (Int32)Events.Count); P += 4; //音符数量 for (int i = 0; i < Events.Count; i++) //音符数据序列 { Midi.write32(data, P, (Int32)(((EventDJZ)Events[i]).time)); P += 4; Midi.write8(data, P, ((EventDJZ)Events[i]).pos); P += 1; Midi.write8(data, P, ((EventDJZ)Events[i]).note); P += 1; } Midi.write32(data, P, (Int32)Controls.Count); P += 4; //控制数量 for (int i = 0; i < Controls.Count; i++) //控制数据序列 { Midi.write32(data, P, (Int32)(((EventDJZ)Controls[i]).time)); P += 4; Midi.write8(data, P, ((EventDJZ)Controls[i]).note); P += 1; Midi.write32(data, P, ((EventDJZ)Controls[i]).metadata); P += 4; } return(data); }
public byte[] toDJZ10() { ////文件结构 ////*文件开始*// //u32 FileSize ; //文件大小 //u32 BPM ; //歌曲速度 (Beat Per Min 拍/分钟) //u32 NoteCount ; //音符数量 //Node* Notes ; //音符数据 ////*文件结束*// ////文件字节流按照 高位存高字节 低位存低字节的顺序 ////音符结构体 (就是游戏中落下的块) //typedef struct { //u32 Time ; //时间 单位 ms , 该音符在什么时间激发 //u8 Line ; //游戏中的轨道 :将由编辑器编辑 //u8 Data ; //发音 (就是MIDI事件的发音) //}Node; EventComparerDJZTime ec = new EventComparerDJZTime(); Events.Sort(ec); Int32 FileSize = 4 + 4 + 4 + Events.Count * 6; byte[] data = new byte[FileSize]; int P = 0; Midi.write32(data, P, (Int32)FileSize); P += 4; //文件大小 Midi.write32(data, P, (Int32)BPM); P += 4; //歌曲速度 (Beat Per Min 拍/分钟) Midi.write32(data, P, (Int32)Events.Count); P += 4; //音符数量 for (int i = 0; i < Events.Count; i++) //音符数据序列 { Midi.write32(data, P, (Int32)(((EventDJZ)Events[i]).time)); P += 4; Midi.write8(data, P, ((EventDJZ)Events[i]).pos); P += 1; Midi.write8(data, P, ((EventDJZ)Events[i]).note); P += 1; //Console.WriteLine("Note[" + i + "].time = " + (Int32)(((Event)Events[i]).time)); } return(data); }
public BMS(Midi mid) { midi = mid; Events = new ArrayList[midi.header.Tracks]; for (int t = 0; t < midi.header.Tracks; t++) { Events[t] = new ArrayList(); int position = 0; for (int i = 0; i < midi.track[t].DeltaTime.Count; i++) { int deltatime = Util.stringDigitToInt(((string)midi.track[t].DeltaTime[i]), 0, ((string)midi.track[t].DeltaTime[i]).Length); position += deltatime; if (EndPos < position) { EndPos = position; } if (midi.track[t].Event[i].ToString() == "Note On") { string str = (string)midi.track[t].Discription[i]; int c = str.IndexOf("Channel="); int n = str.IndexOf("Note="); int v = str.IndexOf("Velocity="); c = Util.stringDigitToInt(str, c + "Channel=".Length, str.Length); n = Util.stringDigitToInt(str, n + "Note=".Length, str.Length); v = Util.stringDigitToInt(str, v + "Velocity=".Length, str.Length); //Console.WriteLine(" c=" + c + " n=" + n + " v=" + v); if (v > 0) { EventBMS ev = new EventBMS(); ev.time = position; ev.note = (byte)n; ev.pos = (byte)n; ev.track = t; ev.used = false; ev.selected = false; ev.dragged = false; Events[t].Add(ev); } } if (midi.track[t].Event[i].ToString() == "Meta : Set Tempo") { string str = (string)midi.track[t].Discription[i]; int tempo = str.IndexOf("Microseconds/Quarter Note="); tempo = Util.stringDigitToInt(str, tempo + "Microseconds/Quarter Note=".Length, str.Length); //Console.WriteLine("tempo="+tempo); EventBMS ev = new EventBMS(); ev.time = position; ev.metadata = tempo; keyBPM.Add(ev); } } } }
public Int32 LoadChunkData(byte[] data, Int32 p) { Int32 P = p; DataSize = Midi.readMSB32(data, P); P += 4; Console.WriteLine("TrackSize : " + DataSize); byte MidiStatus = 0; while ((P - p) < DataSize + 4) { int DataStart = P; /* delta time */ Int32 val = 0; Int32[] vlq = Midi.readVLQ(data, P); P += vlq[0]; val = vlq[1]; String dt = val.ToString(); DeltaTime.Add(dt); //DeltaTime. // Console.Write("DeltaTime : "); // Console.WriteLine(value); /* events */ byte CurByte = Midi.readMSB8(data, P); //midi status changed if (CurByte >= 0x80) { MidiStatus = CurByte; P++; } //8x 1000xxxx nn vv 音符关闭 (释放键盘) nn=音符号 vv=速度 if (MidiStatus >= 0x80 && MidiStatus <= 0x8f) { Event.Add("Note Off"); Discription.Add( "Channel=" + (MidiStatus & 0x0f) + "," + "Note=" + Midi.readMSB8(data, P++) + "," + "Velocity=" + Midi.readMSB8(data, P++) ); //P+=2; } //9x 1001xxxx nn vv 音符打开 (按下键盘) nn=音符号 vv=速度 if (MidiStatus >= 0x90 && MidiStatus <= 0x9f) { Event.Add("Note On"); Discription.Add( "Channel=" + (MidiStatus & 0x0f) + "," + "Note=" + Midi.readMSB8(data, P++) + "," + "Velocity=" + Midi.readMSB8(data, P++) ); //P+=2; } //Ax 1010xxxx nn vv 触摸键盘以后 nn=音符号 vv=速度 if (MidiStatus >= 0xa0 && MidiStatus <= 0xaf) { Event.Add("Polyphone Key Pressure(Aftertouch)"); Discription.Add( "Channel=" + (MidiStatus & 0x0f) + "," + "Note=" + Midi.readMSB8(data, P++) + "," + "Velocity=" + Midi.readMSB8(data, P++) ); //P+=2; } //Bx 1011xxxx cc vv 调换控制 cc=控制号 vv=新值 if (MidiStatus >= 0xb0 && MidiStatus <= 0xbf) { Event.Add("Control Change"); Discription.Add( "Channel=" + (MidiStatus & 0x0f) + "," + "Controller Number=" + Midi.readMSB8(data, P++) + "," + "New Value=" + Midi.readMSB8(data, P++) ); //P+=2; } //Cx 1100xxxx pp 改变程序(片断) pp=新的程序号 if (MidiStatus >= 0xc0 && MidiStatus <= 0xcf) { Event.Add("Program Change"); Discription.Add( "Channel=" + (MidiStatus & 0x0f) + "," + "New Program Number=" + Midi.readMSB8(data, P++) ); //P+=1; } //Dx 1101xxxx cc 在通道后接触 cc=管道号 if (MidiStatus >= 0xd0 && MidiStatus <= 0xdf) { Event.Add("Channel Pressure(Aftertouch)"); Discription.Add( "Channel=" + (MidiStatus & 0x0f) + "," + "cc=" + Midi.readMSB8(data, P++) ); P += 1; } //Ex 1110xxxx bb tt 改变互相咬和的齿轮 (2000H 表明缺省或没有改变)(颤音轮) // bb=值的低7位(least sig) // tt=值的高7位 (most sig) if (MidiStatus >= 0xe0 && MidiStatus <= 0xef) { Event.Add("Pitch Wheel Change"); Discription.Add( "Channel=" + (MidiStatus & 0x0f) + "," + "Bottom=" + Midi.readMSB8(data, P++) + "," + "Top=" + Midi.readMSB8(data, P++) ); //P+=2; } //f0 SYSEX events if (MidiStatus == 0xf0) { int len = 0; vlq = Midi.readVLQ(data, P); P += vlq[0]; Event.Add("SYSEX : (0xf0)"); Discription.Add("..."); len = vlq[1]; P += len; } //F1 MIDI时间代码转换信息 if (MidiStatus == 0xf1) { Event.Add("SYSEX : MIDI Time Code"); Discription.Add(""); } //F2 乐曲位置指针信息 if (MidiStatus == 0xf2) { Event.Add("SYSEX : Song Position Pointer"); Discription.Add("..."); P += 2; } //F3 乐曲选择信息 if (MidiStatus == 0xf3) { Event.Add("SYSEX : Song Select"); Discription.Add("Song=" + Midi.readMSB8(data, P++)); } //F4 (未定义) if (MidiStatus == 0xf4) { Event.Add("(Undefined) (0xf4)"); Discription.Add("..."); } //F5 (未定义) if (MidiStatus == 0xf5) { Event.Add("(Undefined) (0xf5)"); Discription.Add("..."); } //F6 音调调整要求信息 if (MidiStatus == 0xf6) { Event.Add("SYSEX : Tune Request"); Discription.Add(""); } //F7 结束系统专用信息 if (MidiStatus == 0xf7) { Event.Add("SYSEX : End of Exclusive"); Discription.Add(""); } //F8 同步所必须的计时器 if (MidiStatus == 0xf8) { Event.Add("SYSEX : Synchronise Timer"); Discription.Add(""); } //F9 (未定义) if (MidiStatus == 0xf9) { Event.Add("(Undefined) (0xf9)"); Discription.Add("..."); } //FA 开始当前的队列 if (MidiStatus == 0xfa) { Event.Add("SYSEX : Start"); Discription.Add(""); } //FB 从停止的地方继续一个队列 if (MidiStatus == 0xfb) { Event.Add("SYSEX : Continue"); Discription.Add(""); } //FC 停止一个队列 if (MidiStatus == 0xfc) { Event.Add("SYSEX : Stop"); Discription.Add(""); } //FD (未定义) if (MidiStatus == 0xfd) { Event.Add("(Undefined) (0xfd)"); Discription.Add("..."); } //FE 联系激活信息 if (MidiStatus == 0xfe) { Event.Add("SYSEX : Active Sending"); Discription.Add(""); } //FF 复位信息 //if(MidiStatus==0xff){} //ff Meta-Events if (MidiStatus == 0xff) { byte MetaType = Midi.readMSB8(data, P++); byte[] MetaData; int len = 0; vlq = Midi.readVLQ(data, P); P += vlq[0]; len = vlq[1]; MetaData = new byte[len]; System.Array.Copy(data, P, MetaData, 0, len); P += len; //int mp = 0; String text = ""; switch (MetaType) { //00 nn ssss 设定轨道的序号 nn=02 (两字节长度的序号) ssss=序号 case 0x00: Event.Add("Meta : Set Track Number"); Discription.Add(""); break; //01 nn tt .. 你需要的所有文本事件 nn=以字节为单位的文本长度 tt=文本字符 case 0x01: Event.Add("Meta : Text"); for (int i = 0; i < MetaData.Length; i++) { text += ((char)MetaData[i]).ToString(); } Discription.Add(text); break; //02 nn tt .. 同文本的事件, 但是用于版权信息 nn tt=同文本事件 case 0x02: Event.Add("Meta : Copyright"); for (int i = 0; i < MetaData.Length; i++) { text += ((char)MetaData[i]).ToString(); } Discription.Add(text); break; //03 nn tt .. 序列或者轨道名 nn tt=同文本事件 case 0x03: Event.Add("Meta : Track Name"); for (int i = 0; i < MetaData.Length; i++) { text += ((char)MetaData[i]).ToString(); } Discription.Add(text); break; //04 nn tt .. 轨道乐器名 nn tt=同文本事件 case 0x04: Event.Add("Meta : Instrument Name"); for (int i = 0; i < MetaData.Length; i++) { text += ((char)MetaData[i]).ToString(); } Discription.Add(text); break; //05 nn tt .. 歌词 nn tt=同文本事件 case 0x05: Event.Add("Meta : Lyric"); for (int i = 0; i < MetaData.Length; i++) { text += ((char)MetaData[i]).ToString(); } Discription.Add(text); break; //06 nn tt .. 标签 nn tt=同文本事件 case 0x06: Event.Add("Meta : Label"); for (int i = 0; i < MetaData.Length; i++) { text += ((char)MetaData[i]).ToString(); } Discription.Add(text); break; //07 nn tt .. 浮点音符 nn tt=同文本事件 case 0x07: Event.Add("Meta : Float Note"); for (int i = 0; i < MetaData.Length; i++) { text += ((char)MetaData[i]).ToString(); } Discription.Add(text); break; //20 01 cc MIDI Channel 前缀 case 0x20: Event.Add("Meta : MIDI Channel Prefixal"); Discription.Add(MetaData[0].ToString()); break; //2F 00 这个事件一定在每个轨道的结尾出现 case 0x2f: Event.Add("Meta : Track End"); Discription.Add(""); break; //51 03 tttttt 设定拍子 tttttt=微秒/四分音符 case 0x51: Event.Add("Meta : Set Tempo"); int tempo = Midi.readMSB24(MetaData, 0); Discription.Add("Microseconds/Quarter Note=" + tempo + ""); break; //54 05 hh mm ss fr ff SMTPE 偏移量 case 0x54: Event.Add("Meta : SMTPE Offset"); Discription.Add( "HH=" + MetaData[0] + "," + "MM=" + MetaData[1] + "," + "SS=" + MetaData[2] + "," + "FR=" + MetaData[3] + "," + "FF=" + MetaData[4] ); break; //58 04 nn dd cc bb 拍子记号 nn=拍子记号分子 dd=拍子记号分母2=四分之一 3=8分拍, 等等. cc=节拍器的节奏 bb=对四分之一音符标注的第32号数字 case 0x58: Event.Add("Meta : Time Signature"); Discription.Add( "Numerator=" + MetaData[0] + "," + "Denominator=" + MetaData[1] + "," + "Number of Ticks in Metronome Click=" + MetaData[2] + "," + "Number of 32nd Notes to the Quarternote=" + MetaData[3] ); break; //59 02 sf mi 音调符号 sf=升调/降调(-7=7 降调, 0=基准C调,7=7 升调) mi=大调/小调(0=大调, 1=小调) case 0x59: Event.Add("Meta : Key Signature"); Discription.Add( "Sharps or Flats=" + MetaData[0] + "," + "Major or Minor=" + MetaData[1] ); break; //7F xx dd .. 音序器的详细信息 xx=被发送的字节数 dd=数据 case 0x7f: Event.Add("Meta : Synthesizer Info"); for (int i = 0; i < MetaData.Length; i++) { text += ((char)MetaData[i]).ToString(); } Discription.Add(text); break; default: Event.Add("Meta : " + MetaType.ToString("X2")); Discription.Add(""); break; } } String st = ""; for (int i = 0; i < P - DataStart; i++) { st += (data[DataStart + i]).ToString("X2"); st += " "; } HexData.Add(st); byte[] ddata = new byte[P - DataStart]; Array.Copy(data, DataStart, ddata, 0, P - DataStart); dData.Add(ddata); } //P += DataSize; return(DataSize + 4); }
public DJZ(Midi mid, int lineCount) { midi = mid; LineCount = lineCount; Clock = 0; Division = (UInt32)midi.header.Division; Tempo = 500000; SetTempo(Tempo); TrackCount = midi.header.Tracks; Events = new ArrayList[TrackCount]; MidiStatus = new byte[TrackCount]; TrackIndex = new int[TrackCount]; CurClock = new UInt32[TrackCount]; CurTime = new double[TrackCount]; PlayNode = new ArrayList(); Controls = new ArrayList(); Lines = new ArrayList(); LastTime = 0; for (int i = 0; i < TrackCount; i++) { Events[i] = new ArrayList(); MidiStatus[i] = 0; TrackIndex[i] = 0; CurClock[i] = 0; CurTime[i] = 0; } Int32 newTempo = -1; Program = new byte[16]; for (int i = 0; i < Program.Length; i++) { Program[i] = 0; } while (true) { bool end = true; for (int t = 0; t < TrackCount; t++) { while (TrackIndex[t] < midi.track[t].dData.Count) { //End of track end = false; int p = 0; byte[] data = (byte[])(midi.track[t].dData[TrackIndex[t]]); Int32[] vlq = Midi.readVLQ(data, p); p += vlq[0]; Int32 deltatime = vlq[1]; //Track timer is zero if (CurClock[t] == deltatime) { TrackIndex[t]++; CurClock[t] = 0; byte state = Midi.readMSB8(data, p); //midi status changed if (state >= 0x80) { MidiStatus[t] = state; p += 1; } else { state = MidiStatus[t]; } //note on/off if (state >= 0x80 && state <= 0x9f) { EventDJZ ev = new EventDJZ(); ev.time = (UInt32)(CurTime[t] / 1000); ev.state = MidiStatus[t]; ev.note = Midi.readMSB8(data, p); p += 1; ev.channel = (byte)(state & 0x0f); ev.program = Program[ev.channel]; ev.pos = (byte)(ev.note % LineCount); ev.track = t; ev.metadata = 0; ev.fullnote = (int)(Clock / (Division * 4)); ev.used = false; ev.selected = false; ev.dragged = false; ev.DeltaTime = (int)Clock; ev.velo = Midi.readMSB8(data, p); p += 1; //Console.WriteLine("Note : " + ev.time + " : " + ev.note + " : " + ev.track); if (ev.velo != 0 && (state >= 0x90 && state <= 0x9f)) { Events[t].Add(ev); } else//note off { setLastNoteOnLength(Events[t], ev); } } //program change if (state >= 0xc0 && state <= 0xcf) { int channel = (byte)(state & 0x0f); int program = Midi.readMSB8(data, p); p += 1; Program[channel] = (byte)program; } //meta if (state == 0xff) { byte meta = Midi.readMSB8(data, p); p += 1; vlq = Midi.readVLQ(data, p); p += vlq[0]; //meta tempo change if (meta == 0x51) { EventDJZ ev = new EventDJZ(); ev.time = (UInt32)(CurTime[t] / 1000); ev.state = MidiStatus[t]; ev.note = EventDJZ.CONTROL_BPM; ev.pos = 0; ev.track = 0; ev.metadata = 0; ev.fullnote = (int)(Clock / (Division * 4)); ev.used = false; ev.selected = false; ev.dragged = false; ev.DeltaTime = (int)Clock; newTempo = (Int32)Midi.readMSB24(data, p); p += 3; SetTempo((UInt32)newTempo);//Tempo changed ! //Console.WriteLine("Tempo Changed : " + newTempo); ev.metadata = (int)BPM; ev.BPM1000 = (int)(60000000000 / newTempo); Controls.Add(ev); } } } else { break; } } CurTime[t] += TickTime; CurClock[t]++; }//track end if (Clock % (Division * 4) == 0) { EventDJZ ev = new EventDJZ(); ev.time = (UInt32)(LastTime / 1000); ev.fullnote = (int)(Clock / (Division * 4)); ev.DeltaTime = (int)Clock; Lines.Add(ev); // Util.println("count = " + ev.metadata); } LastTime += TickTime; Clock++; if (end) { break; } } LastTime /= 1000; Console.WriteLine("LastTime=" + LastTime + "(ms)"); }