Esempio n. 1
0
        string GetDebugInfo(int nTrackIndex, int nTrackOffset, int delta)
        {
            ushort msg16 = FileHandle.Get16Bit(nTrackIndex, nTrackOffset);
            byte   msg8  = (byte)(msg16 & 0xFF);
            // we want to skip a two-byte header?
            byte msg8Plus1 = FileHandle.Get8Bit(nTrackIndex, nTrackOffset + 2);

            CurrentStatus = msg16;
            return($"{{ Track Index: {nTrackIndex}, Track Offset: {nTrackOffset}, delta: {delta} }}\n" +
                   $"{{ 16 Bit Message: {msg16:X4}, 8 Bit Message: {msg8:X2}, next 8 Bit Message: {msg8Plus1:X2};");
        }
Esempio n. 2
0
        /// <inheritdoc/>
        public string GetMessageString(int pTrackIndex, int pTrackOffset)
        {
            var msg32 = FileHandle.Get16Bit(pTrackIndex, pTrackOffset);

            switch ((StatusWord)msg32)
            {
            case StatusWord.SequenceNumber: /* 0xFF00 */ return(MetaHelpers.meta_FF00(FileHandle[pTrackIndex, pTrackOffset + 3], FileHandle[pTrackIndex, pTrackOffset + 4]));

            case StatusWord.ChannelPrefix:      /* 0xFF20 */
            case StatusWord.PortMessage: /* 0xFF21 */ return(FileHandle[pTrackIndex, pTrackOffset + 3].ToString());

            case StatusWord.SetTempo: /* 0xFF51 */ return(MetaHelpers.meta_FF51(Convert.ToInt32(FileHandle[pTrackIndex].ReadU24(pTrackOffset + 3))));

            case StatusWord.SMPTEOffset: /* 0xFF54 */ return(MetaHelpers.meta_FF54(this, pTrackOffset));

            case StatusWord.TimeSignature: /* 0xFF58 */ return(MetaHelpers.meta_FF58(FileHandle[pTrackIndex], pTrackOffset));

            case StatusWord.KeySignature: /* 0xFF59 */ return(MetaHelpers.PrintKeysignature(FileHandle[pTrackIndex], pTrackOffset));

            case StatusWord.EndOfTrack: /* 0xFF2F */ return(MetaHelpers.meta_FF2F());

            case StatusWord.SequencerSpecific_FF70: /* 0xFF70 */ return(GetMetadataBytes(pTrackIndex, pTrackOffset).StringifyHex());

            case StatusWord.SequencerSpecific_FF71: /* 0xFF71 */ return(GetMetadataBytes(pTrackIndex, pTrackOffset).StringifyHex());

            case StatusWord.SequencerSpecific_FF72: /* 0xFF72 */ return(GetMetadataBytes(pTrackIndex, pTrackOffset).StringifyHex());

            case StatusWord.SequencerSpecific_FF73: /* 0xFF73 */ return(GetMetadataBytes(pTrackIndex, pTrackOffset).StringifyHex());

            case StatusWord.SequencerSpecific_FF74: /* 0xFF74 */ return(GetMetadataBytes(pTrackIndex, pTrackOffset).StringifyHex());

            case StatusWord.SequencerSpecific_FF75: /* 0xFF75 */ return(GetMetadataBytes(pTrackIndex, pTrackOffset).StringifyHex());

            case StatusWord.SequencerSpecific_FF76: /* 0xFF76 */ return(GetMetadataBytes(pTrackIndex, pTrackOffset).StringifyHex());

            case StatusWord.SequencerSpecific_FF77: /* 0xFF77 */ return(GetMetadataBytes(pTrackIndex, pTrackOffset).StringifyHex());

            case StatusWord.SequencerSpecific_FF78: /* 0xFF78 */ return(GetMetadataBytes(pTrackIndex, pTrackOffset).StringifyHex());

            case StatusWord.SequencerSpecific_FF79: /* 0xFF79 */ return(GetMetadataBytes(pTrackIndex, pTrackOffset).StringifyHex());

            case StatusWord.SequencerSpecific_FF7A: /* 0xFF7A */ return(GetMetadataBytes(pTrackIndex, pTrackOffset).StringifyHex());

            case StatusWord.SequencerSpecific_FF7B: /* 0xFF7B */ return(GetMetadataBytes(pTrackIndex, pTrackOffset).StringifyHex());

            case StatusWord.SequencerSpecific_FF7C: /* 0xFF7C */ return(GetMetadataBytes(pTrackIndex, pTrackOffset).StringifyHex());

            case StatusWord.SequencerSpecific_FF7D: /* 0xFF7D */ return(GetMetadataBytes(pTrackIndex, pTrackOffset).StringifyHex());

            case StatusWord.SequencerSpecific_FF7E: /* 0xFF7E */ return(GetMetadataBytes(pTrackIndex, pTrackOffset).StringifyHex());

            case StatusWord.SequencerSpecific: /* 0xFF7F */ return(GetMetadataBytes(pTrackIndex, pTrackOffset).StringifyHex());

            case StatusWord.SystemExclusive:    /* 0xF0 */
                int    nlength = FileHandle[pTrackIndex].GetEndOfSystemExclusive(pTrackOffset) - pTrackOffset;
                int    noffset = pTrackOffset;
                string nresult = FileHandle[pTrackIndex, pTrackOffset, nlength].StringifyHex();
                return(nresult);

            default: // check for a channel message
                if (CurrentRunningStatus8 == 0xF0)
                {
                    long ro = 0;
                    int  no = FileHandle.ReadDelta(pTrackIndex, pTrackOffset + 1, out ro) - pTrackOffset;
                    return(FileHandle[pTrackIndex, pTrackOffset, Convert.ToInt32(ro) + 2].StringifyHex());
                }
                // string msg = string.Format(StringRes.String_Unknown_Message, CurrentRunningStatus8, FileHandle[pTrackIndex, pTrackOffset, 2].StringifyHex());
                return(Strings.Encoding.GetString(FileHandle[pTrackIndex, pTrackOffset, FileHandle[pTrackIndex, pTrackOffset + 2] + 3]));
            }
        }
Esempio n. 3
0
        /// <summary>
        /// In MIDI Format 1, this would be the first track (index = 0).
        /// Otherwise Format 0: index = 0 and with
        /// Format 2, each track will essentially be like a Format 0 track.
        ///
        /// This method collects information from the 'tempo map' track such as
        ///
        /// - Tempo Information
        /// - SMPTE Offset
        /// - Time Signature
        /// - Key Signatuer
        /// - Sequencer Specific Data
        /// - System Exclusive Data (in tempo map)
        /// </summary>
        int GetTempoMap(int nTrackIndex, int nTrackOffset, int delta)
        {
            int  DELTA_Returned = delta;
            var  msg16          = FileHandle.Get16Bit(nTrackIndex, nTrackOffset);
            byte msg8           = (byte)(msg16 & 0xFF);

            CurrentStatus = msg16; // This is just an attempt at aligning running status.
            // var hexMsg = $"{msg16:X2}";
            if (msg16 >= 0xFF00 && msg16 <= 0xFF0C)
            {
                DELTA_Returned = FileHandle.Tracks[nTrackIndex].DeltaSeek(nTrackOffset);
                return(++DELTA_Returned);
            }
            switch (msg16)
            {
            // text
            case Stat16.SequenceNumber: // 0xFF00
            case Stat16.ChannelPrefix:  // 0xFF20
            case Stat16.PortMessage: /* 0xFF21 */ DELTA_Returned = FileHandle.Tracks[nTrackIndex].DeltaSeek(nTrackOffset); break;

            case Stat16.EndOfTrack: /* 0xFF2F */ DELTA_Returned = FileHandle.Tracks[nTrackIndex].Data.Length - 1; break;

            case Stat16.SetTempo: // 0xFF51
                var muspqn = FileHandle[ReaderIndex].ReadU24(nTrackOffset + 3);
                TempoMap.Push(muspqn, Division, CurrentTrackPulse);
                DELTA_Returned = FileHandle.Tracks[nTrackIndex].DeltaSeek(nTrackOffset);
                break;

            case Stat16.SMPTEOffset: // 0xFF54
                SMPTE.SetSMPTE(
                    FileHandle.Tracks[nTrackIndex].Data[nTrackOffset + 3],
                    FileHandle.Tracks[nTrackIndex].Data[nTrackOffset + 4],
                    FileHandle.Tracks[nTrackIndex].Data[nTrackOffset + 5],
                    FileHandle.Tracks[nTrackIndex].Data[nTrackOffset + 6],
                    FileHandle.Tracks[nTrackIndex].Data[nTrackOffset + 7]
                    );
                DELTA_Returned = FileHandle.Tracks[nTrackIndex].DeltaSeek(nTrackOffset);
                break;

            case Stat16.TimeSignature: // 0xFF58
                TimeSignature.SetSignature(
                    (int)this[nTrackIndex, nTrackOffset + 3],
                    (int)Math.Pow(-this[nTrackIndex, nTrackOffset + 4], 2),
                    (int)this[nTrackIndex, nTrackOffset + 5],
                    (int)this[nTrackIndex, nTrackOffset + 6]
                    );
                DELTA_Returned = FileHandle.Tracks[nTrackIndex].DeltaSeek(nTrackOffset);
                break;

            case Stat16.KeySignature: // 0xFF59
                KeySignature.SetSignature(
                    this[nTrackIndex, nTrackOffset + 3],
                    this[nTrackIndex, nTrackOffset + 4]);
                DELTA_Returned = FileHandle.Tracks[nTrackIndex].DeltaSeek(nTrackOffset);
                break;

            case Stat16.SequencerSpecific_70: // 0xFF70
            case Stat16.SequencerSpecific_71: // 0xFF71
            case Stat16.SequencerSpecific_72: // 0xFF72
            case Stat16.SequencerSpecific_73: // 0xFF73
            case Stat16.SequencerSpecific_74: // 0xFF74
            case Stat16.SequencerSpecific_75: // 0xFF75
            case Stat16.SequencerSpecific_76: // 0xFF76
            case Stat16.SequencerSpecific_77: // 0xFF77
            case Stat16.SequencerSpecific_78: // 0xFF78
            case Stat16.SequencerSpecific_79: // 0xFF79
            case Stat16.SequencerSpecific_7A: // 0xFF7A
            case Stat16.SequencerSpecific_7B: // 0xFF7B
            case Stat16.SequencerSpecific_7C: // 0xFF7C
            case Stat16.SequencerSpecific_7D: // 0xFF7D
            case Stat16.SequencerSpecific_7E: // 0xFF7E
            case Stat16.SequencerSpecific:    // 0xFF7F
                DELTA_Returned = FileHandle.Tracks[nTrackIndex].DeltaSeek(nTrackOffset);
                break;

            case Stat16.SystemExclusive:
                var pLastIndex = FileHandle[nTrackIndex].GetEndOfSystemExclusive(nTrackOffset);
                DELTA_Returned = pLastIndex;
                break;

            default:
            {
                if (FileHandle.Tracks[nTrackIndex].Data[nTrackOffset] < 0x80)
                {
                    CurrentStatus = CurrentRunningStatus16;
                    // Running Status
                    // int ExpandedRSE = CurrentTrackRunningStatus;// << 8;
                    int ExpandedRSE = CurrentRunningStatus8;// << 8;
                    int delta1      = -1;
                    if ((delta1 = Increment(nTrackOffset)) == -1)
                    {
                        int test = GetOffset(nTrackIndex, nTrackOffset);
                        Debug.Assert(false, string.Format("warning… {0:X2}, {1:X}|{1:N0}", ExpandedRSE, test));
                    }
                    else
                    {
                        DELTA_Returned = delta1;
                    }
                }
                else if (StatusQuery.IsMidiMessage(msg8))
                {
                    CurrentRunningStatus8  = msg8;
                    CurrentRunningStatus16 = msg16;
                    DELTA_Returned         = Increment(nTrackOffset + 1);
                    return(++DELTA_Returned);
                }
                else
                {
                    throw new FormatException("Bad format!\nThere is probably a problem with the Input File unless we made an error reading it!)");
                }
            }

            break;
            }
            return(++DELTA_Returned);
        }
Esempio n. 4
0
        /// <summary>
        /// provides **default parser semantic** in that from here we delegate
        /// each message to <see cref="MessageHandler"/>.
        /// `MessageHandler` can be set via the constructor, or explicitly after
        /// initializing (creating/.ctor) `Reader`.
        ///
        /// Additionally, <see cref="OnMidiMessage(MidiMsgType, int, int, int, byte, long, int, bool)"/>
        /// exists and can be set as the default message-handler in which case any assigned
        /// event handler(s) (`ProcessMidiMessage`) or delegates (`MessageHandler`)
        /// can and will be used.
        /// </summary>
        public virtual int GetNTrackMessage(int nTrackIndex, int nTrackOffset, int delta)
        {
            int    DELTA_Returned = delta;
            ushort msg16          = FileHandle.Get16Bit(nTrackIndex, nTrackOffset);
            byte   msg8           = (byte)(msg16 & 0xFF);

            CurrentStatus = msg16;
            // var hexMsg = $"{msg16:X2}";
            if (msg16 >= 0xFF00 && msg16 <= 0xFF0C)
            {
                MessageHandler(MidiMsgType.MetaStr, nTrackIndex, nTrackOffset, msg16, msg8, CurrentTrackPulse, CurrentRunningStatus8, false);
                DELTA_Returned = FileHandle.Tracks[nTrackIndex].DeltaSeek(nTrackOffset);
                return(++DELTA_Returned);
            }
            switch (msg16)
            {
            case Stat16.EndOfTrack:  // FF2F
                MessageHandler(MidiMsgType.EOT, nTrackIndex, nTrackOffset, msg16, msg8, CurrentTrackPulse, CurrentRunningStatus8, false);
                DELTA_Returned = FileHandle.Tracks[nTrackIndex].Data.Length;
                break;

            case Stat16.SequenceNumber: // 0xFF00
            case Stat16.ChannelPrefix:  // FF20
            case Stat16.PortMessage:    // FF21?
            case Stat16.SetTempo:       // FF51
                MessageHandler(MidiMsgType.MetaInf, nTrackIndex, nTrackOffset, msg16, msg8, CurrentTrackPulse, CurrentRunningStatus8, false);
                DELTA_Returned = FileHandle.Tracks[nTrackIndex].DeltaSeek(nTrackOffset);
                break;

            case Stat16.SMPTEOffset: // FF54
                MessageHandler(MidiMsgType.MetaInf, nTrackIndex, nTrackOffset, msg16, msg8, CurrentTrackPulse, CurrentRunningStatus8, false);
                DELTA_Returned = FileHandle.Tracks[nTrackIndex].DeltaSeek(nTrackOffset);
                break;

            case Stat16.TimeSignature: // FF58
            case Stat16.KeySignature:  // FF59
                MessageHandler(MidiMsgType.MetaInf, nTrackIndex, nTrackOffset, msg16, msg8, CurrentTrackPulse, CurrentRunningStatus8, false);
                DELTA_Returned = FileHandle.Tracks[nTrackIndex].DeltaSeek(nTrackOffset);
                break;

            case Stat16.SequencerSpecific_70: // 0xFF70
            case Stat16.SequencerSpecific_71: // 0xFF71
            case Stat16.SequencerSpecific_72: // 0xFF72
            case Stat16.SequencerSpecific_73: // 0xFF73
            case Stat16.SequencerSpecific_74: // 0xFF74
            case Stat16.SequencerSpecific_75: // 0xFF75
            case Stat16.SequencerSpecific_76: // 0xFF76
            case Stat16.SequencerSpecific_77: // 0xFF77
            case Stat16.SequencerSpecific_78: // 0xFF78
            case Stat16.SequencerSpecific_79: // 0xFF79
            case Stat16.SequencerSpecific_7A: // 0xFF7A
            case Stat16.SequencerSpecific_7B: // 0xFF7B
            case Stat16.SequencerSpecific_7C: // 0xFF7C
            case Stat16.SequencerSpecific_7D: // 0xFF7D
            case Stat16.SequencerSpecific_7E: // 0xFF7E
                // we have FF70LLNN where LL is a byte length (assumed: variable bit) and NN is the data we're being provided.
                // MPC Pro software generates it.
                // Theoretically, this could probably happen for other FF70-FF7E?
                MessageHandler(MidiMsgType.SequencerSpecificUnknown, nTrackIndex, nTrackOffset, msg16, msg8, CurrentTrackPulse, CurrentRunningStatus8, false);
                DELTA_Returned = FileHandle.Tracks[nTrackIndex].DeltaSeek(nTrackOffset);
                break;

            case Stat16.SequencerSpecific: // FF7F
                MessageHandler(MidiMsgType.SequencerSpecific, nTrackIndex, nTrackOffset, msg16, msg8, CurrentTrackPulse, CurrentRunningStatus8, false);
                DELTA_Returned = FileHandle.Tracks[nTrackIndex].DeltaSeek(nTrackOffset);
                break;

            case Stat16.SystemExclusive: // 0xF0
                MessageHandler(MidiMsgType.SystemExclusive, nTrackIndex, nTrackOffset, msg16, msg8, CurrentTrackPulse, CurrentRunningStatus8, false);
                DELTA_Returned = FileHandle[nTrackIndex].GetEndOfSystemExclusive(nTrackOffset);
                break;

            default:
            {
                if (FileHandle.Tracks[nTrackIndex].Data[nTrackOffset] < 0x80) // running-status message
                {
                    // Running Status
                    CurrentStatus = CurrentRunningStatus16;

                    int ExpandedRSE = CurrentRunningStatus8;// << 8;
                    int delta1      = -1;
                    if ((delta1 = Increment(nTrackOffset)) == -1)
                    {
                        int test = GetOffset(nTrackIndex, nTrackOffset);
                        Debug.Assert(false, string.Format("warning… {0:X2}, {1:X}|{1:N0}", ExpandedRSE, test));
                    }
                    else
                    {
                        DELTA_Returned = delta1;
                        MessageHandler(GetMidiMessageType(CurrentRunningStatus8), nTrackIndex, nTrackOffset, CurrentRunningStatus16, (byte)CurrentRunningStatus8, CurrentTrackPulse, CurrentRunningStatus8, true);
                    }
                }
                //else if (StatusQuery.IsMidiMessage(msg32))
                else if (StatusQuery.IsMidiMessage(msg8))
                {
                    //CurrentTrackRunningStatus = (FileHandle[nTrackIndex, nTrackOffset]);
                    CurrentRunningStatus8  = msg8;
                    CurrentRunningStatus16 = msg16;
                    DELTA_Returned         = Increment(nTrackOffset + 1);
                    MessageHandler(GetMidiMessageType(CurrentRunningStatus8), nTrackIndex, nTrackOffset, msg16, msg8, CurrentTrackPulse, CurrentRunningStatus8, false);
                    DELTA_Returned++;
                    return(DELTA_Returned);
                }
                else
                {
                    throw new FormatException(
                              $"Bad format(?)!\n" +
                              $"There is probably a problem with the Input File (unless we made an error reading it)!\n" +
                              $"Here is some debug info: {GetDebugInfo(nTrackIndex, nTrackOffset, delta)}");
                }
            }

            break;
            }
            return(++DELTA_Returned);
        }