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)"); }