Exemplo n.º 1
0
        /* add another byte to the MIDI event */
        public static void RawMIDIEventAppendByte(
            RawMIDIEventRec RawEvent,
            byte Byte)
        {
            int Length = RawEvent.Message.Length;

            Array.Resize(ref RawEvent.Message, RawEvent.Message.Length + 1);
            RawEvent.Message[Length] = Byte;
        }
Exemplo n.º 2
0
        /* create a new MIDI event */
        public static RawMIDIEventRec NewRawMIDIEvent(
            int Time,
            byte Status)
        {
            RawMIDIEventRec RawEvent = new RawMIDIEventRec();

            RawEvent.Message = new byte[0];
            RawEvent.Time    = Time;
            RawEvent.Status  = Status;
            RawEvent.AuxType = 0;

            return(RawEvent);
        }
        /* convert raw track into an interval track.  MIDITrackNum should be in 1..16 */
        /* *KeepFlag is set if there were real events in this track. */
        public static void ConvertRawToInterval(
            RawMIDITrackRec RawTrack,
            IntervalTrackRec IntervalTrack,
            short MIDITrackNum,
            out bool KeepFlag)
        {
            int Limit;

            PitchEventRec[] EventTracker = new PitchEventRec[128];

            Debug.Assert((MIDITrackNum >= 1) || (MIDITrackNum <= 16));
            MIDITrackNum -= 1;
            KeepFlag      = false;

            /* initialize correlation tracker */
            for (int i = 0; i < 128; i += 1)
            {
                EventTracker[i].NoteOn = false;
            }

            /* scan all low level events */
            Limit = GetRawMIDITrackLength(RawTrack);
            for (int i = 0; i < Limit; i += 1)
            {
                byte TypeByte;

                RawMIDIEventRec RawEvent   = GetRawMIDITrackIndexedEvent(RawTrack, i);
                byte            StatusByte = GetRawMIDIEventStatus(RawEvent);
                switch ((StatusByte >> 4) & 0x0f)
                {
                /* ignore events we don't know about */
                default:
                    break;

                /* 1000nnnn:  note off event for channel nnnn followed by 2 data bytes */
                case 0x08:
NoteOffPoint:
                    if ((StatusByte & 0x0f) == MIDITrackNum)
                    {
                        short Pitch;
                        short ReleaseVelocity;

                        /* data byte 1:  velocity 0..127 */
                        /* data byte 2:  pitch 0..127 */
                        if (GetRawMIDIEventMessageLength(RawEvent) >= 2)
                        {
                            ReleaseVelocity = (short)(0x7f & GetRawMIDIEventMessageByte(RawEvent, 1));
                        }
                        else
                        {
                            ReleaseVelocity = 0;
                        }
                        if (GetRawMIDIEventMessageLength(RawEvent) >= 1)
                        {
                            Pitch = (short)(0x7f & GetRawMIDIEventMessageByte(RawEvent, 0));
                        }
                        else
                        {
                            Pitch = 0;
                        }
                        if (EventTracker[Pitch].NoteOn)
                        {
                            IntEventRec IntervalEvent = NewIntervalNoteEvent(
                                EventTracker[Pitch].StartTime,
                                GetRawMIDIEventTime(RawEvent) - EventTracker[Pitch].StartTime,
                                Pitch,
                                EventTracker[Pitch].StartVelocity,
                                ReleaseVelocity);
                            IntervalTrackInsertEventSorted(IntervalTrack, IntervalEvent);
                            EventTracker[Pitch].NoteOn = false;
                        }
                        else
                        {
                            /* no note-on event? */
                        }
                        KeepFlag = true;
                    }
                    break;

                /* 1001nnnn:  note on event for channel nnnn followed by 2 data bytes */
                case 0x09:
                    if ((StatusByte & 0x0f) == MIDITrackNum)
                    {
                        short Pitch;
                        short Velocity;

                        /* data byte 1:  velocity 0..127 */
                        /* data byte 2:  pitch 0..127 */
                        if (GetRawMIDIEventMessageLength(RawEvent) >= 2)
                        {
                            Velocity = (short)(0x7f & GetRawMIDIEventMessageByte(RawEvent, 1));
                        }
                        else
                        {
                            Velocity = 64;
                        }
                        if (Velocity == 0)
                        {
                            /* note on velocity 0 actually means note off */
                            goto NoteOffPoint;
                        }
                        if (GetRawMIDIEventMessageLength(RawEvent) >= 1)
                        {
                            Pitch = (short)(0x7f & GetRawMIDIEventMessageByte(RawEvent, 0));
                        }
                        else
                        {
                            Pitch = 0;
                        }
                        if (!EventTracker[Pitch].NoteOn)
                        {
                            EventTracker[Pitch].StartTime     = GetRawMIDIEventTime(RawEvent);
                            EventTracker[Pitch].StartVelocity = Velocity;
                            EventTracker[Pitch].NoteOn        = true;
                        }
                        else
                        {
                            /* note already on? */
                        }
                        KeepFlag = true;
                    }
                    break;

                /* 1010nnnn:  polyphonic key pressure/after touch followed by */
                /*   2 data bytes */
                case 0x0a:
                    break;

                /* 1011nnnn:  control change followed by 2 data bytes */
                case 0x0b:
                    break;

                /* 1110nnnn:  pitch bend change followed by 2 data bytes */
                case 0x0e:
                    break;

                /* 1100nnnn:  program change followed by 1 data byte */
                case 0x0c:
                    break;

                /* 1101nnnn:  channel pressure/after touch followed by 1 data byte */
                case 0x0d:
                    break;

                /* assorted thangs */
                case 0x0f:
                    switch (StatusByte & 0x0f)
                    {
                    default:
                        break;

                    /* 11110000:  initial or solitary SYSEX message.  followed by a */
                    /*   variable length field.  solitary message is terminated by */
                    /*   0xf7 (which is not part of the message, but is included in */
                    /*   length).  continuing message does not end with 0xf7. */
                    /*   NOTE:  SYSEX also cancels the running status. */
                    /* 11110111:  continuing SYSEX message.  same format as initial. */
                    case 0x00:
                    case 0x07:
                    {
                        StringBuilder sb = new StringBuilder();
                        if ((StatusByte & 0x0f) == 0x00)
                        {
                            sb.AppendLine("System Exclusive $F0");
                        }
                        else
                        {
                            sb.AppendLine("System Exclusive $F7");
                        }
                        int c = GetRawMIDIEventMessageLength(RawEvent);
                        for (int j = 0; j < c; j += 1)
                        {
                            byte b = GetRawMIDIEventMessageByte(RawEvent, j);
                            sb.Append('$');
                            sb.Append(HexBuf[(b >> 4) & 0x0f]);
                            sb.Append(HexBuf[b & 0x0f]);
                            if (((j + 1) % SYSEXBYTESPERLINE) == 0)
                            {
                                sb.AppendLine();
                            }
                            else
                            {
                                sb.Append(' ');
                            }
                        }
                        IntEventRec IntervalEvent = NewIntervalCommentEvent(GetRawMIDIEventTime(RawEvent), sb.ToString());
                        IntervalTrackInsertEventSorted(IntervalTrack, IntervalEvent);
                    }
                    break;

                    /* 11110010:  song position pointer, followed by 2 data bytes */
                    case 0x02:
                    {
                        StringBuilder String;
                        string        Buffer;
                        IntEventRec   IntervalEvent;

                        String = new StringBuilder();
                        String.Append("Song Position Pointer" + Environment.NewLine);
                        if (GetRawMIDIEventMessageLength(RawEvent) >= 2)
                        {
                            String.Append((int)((GetRawMIDIEventMessageByte(RawEvent, 0) & 0x7f)
                                                | ((GetRawMIDIEventMessageByte(RawEvent, 1) & 0x7f) << 7)));
                        }
                        else
                        {
                            String.Append((int)0);
                        }
                        Buffer        = String.ToString();
                        IntervalEvent = NewIntervalCommentEvent(GetRawMIDIEventTime(RawEvent), Buffer);
                        IntervalTrackInsertEventSorted(IntervalTrack, IntervalEvent);
                    }
                    break;

                    /* 11110011:  song select, followed by 2 data bytes */
                    case 0x03:
                    {
                        StringBuilder String;
                        string        Buffer;
                        IntEventRec   IntervalEvent;

                        String = new StringBuilder();
                        String.Append("Song Select" + Environment.NewLine);
                        if (GetRawMIDIEventMessageLength(RawEvent) >= 2)
                        {
                            String.Append((int)((GetRawMIDIEventMessageByte(RawEvent, 0) & 0x7f)
                                                | ((GetRawMIDIEventMessageByte(RawEvent, 1) & 0x7f) << 7)));
                        }
                        else
                        {
                            String.Append((int)0);
                        }
                        Buffer        = String.ToString();
                        IntervalEvent = NewIntervalCommentEvent(GetRawMIDIEventTime(RawEvent), Buffer);
                        IntervalTrackInsertEventSorted(IntervalTrack, IntervalEvent);
                    }
                    break;

                    /* 11110110:  tune request, no data */
                    case 0x06:
                    {
                        string      String;
                        IntEventRec IntervalEvent;

                        String        = "Tune Request";
                        IntervalEvent = NewIntervalCommentEvent(GetRawMIDIEventTime(RawEvent), String);
                        IntervalTrackInsertEventSorted(IntervalTrack, IntervalEvent);
                    }
                    break;

                    /* 11111111:  meta event.  followed by type byte (0..127) and */
                    /*   then variable length specifier, then data bytes. */
                    case 0x0f:
                        /* check out the auxilliary type */
                        TypeByte = GetRawMIDIEventTypeByte(RawEvent);
                        switch (TypeByte)
                        {
                        default:
                            break;

                        /* (FF) 01 <len> <text>:  text event */
                        /* (FF) 02 <len> <text>:  copyright */
                        /* (FF) 03 <len> <text>:  sequence/track name */
                        /* (FF) 04 <len> <text>:  instrument name */
                        /* (FF) 05 <len> <text>:  lyric */
                        /* (FF) 06 <len> <text>:  marker */
                        /* (FF) 07 <len> <text>:  cue point */
                        case 0x01:
                        case 0x02:
                        case 0x03:
                        case 0x04:
                        case 0x05:
                        case 0x06:
                        case 0x07:
                        {
                            string      String;
                            char[]      Text;
                            IntEventRec IntervalEvent;
                            string      Combined;
                            int         Length;
                            int         Scan2;

                            switch (GetRawMIDIEventTypeByte(RawEvent))
                            {
                            default:
                                Debug.Assert(false);
                                throw new InvalidOperationException();

                            /* (FF) 01 <len> <text>:  text event */
                            /* (FF) 02 <len> <text>:  copyright */
                            /* (FF) 03 <len> <text>:  sequence/track name */
                            /* (FF) 04 <len> <text>:  instrument name */
                            /* (FF) 05 <len> <text>:  lyric */
                            /* (FF) 06 <len> <text>:  marker */
                            /* (FF) 07 <len> <text>:  cue point */
                            case 0x01:
                                String = "Comment" + Environment.NewLine;
                                break;

                            case 0x02:
                                String = "Copright" + Environment.NewLine;
                                break;

                            case 0x03:
                                String = "Track Name" + Environment.NewLine;
                                break;

                            case 0x04:
                                String = "Instrument Name" + Environment.NewLine;
                                break;

                            case 0x05:
                                String = "Lyric" + Environment.NewLine;
                                break;

                            case 0x06:
                                String = "Marker" + Environment.NewLine;
                                break;

                            case 0x07:
                                String = "Cue Point" + Environment.NewLine;
                                break;
                            }
                            Length = GetRawMIDIEventMessageLength(RawEvent);
                            if (Length > 0)
                            {
                                /* don't deal with the first character since it */
                                /* isn't part of the text */
                                Length -= 1;
                            }
                            Text = new char[Length + Environment.NewLine.Length];
                            for (Scan2 = 0; Scan2 < Length; Scan2 += 1)
                            {
                                Text[Scan2] = (char)GetRawMIDIEventMessageByte(RawEvent, Scan2 + 1 /*skip first character*/);
                            }
                            Text[Length]     = Environment.NewLine[0];
                            Text[Length + 1] = Environment.NewLine[1];
                            Combined         = String.Concat(String, new String(Text));
                            IntervalEvent    = NewIntervalCommentEvent(GetRawMIDIEventTime(RawEvent), Combined);
                            IntervalTrackInsertEventSorted(IntervalTrack, IntervalEvent);
                        }
                        break;

                            /* (FF) 00 <02> ss ss:  sequence number */
                            /* (FF) 2F <00>:  end of track */
                            /* (FF) 51 <03> tt tt tt:  set tempo (microsec/quarter note) */
                            /* (FF) 54 <05> hr mn se fr ff:  SMTPE offset */
                            /* (FF) 58 <04> nn dd cc bb: time signature */
                            /*    nn/dd is numerator/denominator.  dd is a negative power */
                            /*    of two (2=quarter note, 3=eighth note). */
                            /*    cc = midi clocks per metronome click. */
                            /*    bb = number of 32nd notes per quarter note (24 clocks) */
                            /* (FF) 59 <02> sf mi:  key signature */
                            /*    sf: -7..-1 flats, 0 = normal, 1..7 = sharps */
                            /*    mi = 0 or major, 1 for minor */
                            /* (FF) 7F <len> <data>:  sequencer meta event */
                        }
                        break;
                    }
                    break;
                }
            }
        }
Exemplo n.º 4
0
 /* get a message byte */
 public static byte GetRawMIDIEventMessageByte(
     RawMIDIEventRec RawEvent,
     int Index)
 {
     return(RawEvent.Message[Index]);
 }
Exemplo n.º 5
0
 /* get message length */
 public static int GetRawMIDIEventMessageLength(RawMIDIEventRec RawEvent)
 {
     return(RawEvent.Message.Length);
 }
Exemplo n.º 6
0
 /* get status */
 public static byte GetRawMIDIEventStatus(RawMIDIEventRec RawEvent)
 {
     return(RawEvent.Status);
 }
Exemplo n.º 7
0
 /* get time */
 public static int GetRawMIDIEventTime(RawMIDIEventRec RawEvent)
 {
     return(RawEvent.Time);
 }
Exemplo n.º 8
0
 /* get auxilliary type byte */
 public static byte GetRawMIDIEventTypeByte(RawMIDIEventRec RawEvent)
 {
     return(RawEvent.AuxType);
 }
Exemplo n.º 9
0
 /* set auxilliary type byte */
 public static void SetRawMIDIEventTypeByte(
     RawMIDIEventRec RawEvent,
     byte Byte)
 {
     RawEvent.AuxType = Byte;
 }
Exemplo n.º 10
0
 /* append a new MIDI event to the track */
 public static void RawMIDITrackAppendEvent(
     RawMIDITrackRec RawTrack,
     RawMIDIEventRec Event)
 {
     RawTrack.EventList.Add(Event);
 }