Beispiel #1
0
        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);
        }
Beispiel #2
0
        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)");
        }