예제 #1
0
        /// <summary>
        /// Create a Sysex event
        /// </summary>
        /// <param name="data">a String that represents the data for the event.</param>
        /// <param name="tick">the position of the event in the sequence</param>
        /// <returns>the created Midi Sysex event</returns>
        public static MidiEvent CreateSysexEvent(string data, long tick)
        {
            var bytes = MidiHelper.StringToByteArray(data, ",");

            if (bytes.Length == 0)
            {
                throw new InvalidProgramException(string.Format("Could not parse the passed sysex event {0}", data));
            }

            var sysexMessage = new SysexMessage();

            sysexMessage.SetMessage(bytes, bytes.Length);             // use base method to set the whole sysex message in one go
            var ev = new MidiEvent(sysexMessage, tick);

            return(ev);
        }
예제 #2
0
        /// <summary>
        /// Get the MIDI Sequence found in this input stream.
        /// <see cref="gnu.sound.midi.spi.MidiFileReader#GetSequence(Stream)"/>
        /// </summary>
        public override Sequence GetSequence(Stream stream)
        {
            // Good midi spec:
            // http://www.somascape.org/midi/tech/mfile.html
            // http://www.ccarh.org/courses/253/handout/smf/

            var din = new MidiDataInputStream(stream);
            var mff = (ExtendedMidiFileFormat)GetMidiFileFormat(din.BaseStream);

            var seq = new Sequence(mff.DivisionType, mff.Resolution, 0, mff.MidiFileType);

            int ntracks = mff.NumberOfTracks;

            while (ntracks-- > 0)
            {
                Track track = seq.CreateTrack();
                int   Mtrk  = din.ReadInt32();
                if (Mtrk != 0x4D54726B)                 // "MTrk"
                {
                    throw new InvalidMidiDataException("Invalid MIDI track header.");
                }
                int length = din.ReadInt32();

                int runningStatus = -1;
                int click         = 0;

                // Set this to true when we've hit an End of Track meta event.
                bool done = false;

                // Read all events.
                while (!done)
                {
                    MidiMessage mm;
                    int         deltaTime = din.ReadVariableLengthInt();
                    click += deltaTime;

                    // in Java bytes are signed (-128, +127)
                    // where in C# it's not (0, 255).
                    int statusByte = din.ReadByte();

                    if (statusByte < (int)MidiHelper.MidiEventType.SystemExclusive)
                    {
                        ShortMessage shortMessage;
                        switch (statusByte & 0xF0)
                        {
                        case (int)MidiHelper.MidiEventType.NoteOff:
                        case (int)MidiHelper.MidiEventType.NoteOn:
                        case (int)MidiHelper.MidiEventType.AfterTouchPoly:
                        case (int)MidiHelper.MidiEventType.ControlChange:
                        case (int)MidiHelper.MidiEventType.PitchBend:
                        case (int)MidiHelper.MidiEventType.SongPosition:
                            shortMessage = new ShortMessage();
                            shortMessage.SetMessage(statusByte, din.ReadByte(), din.ReadByte());
                            runningStatus = statusByte;
                            break;

                        case (int)MidiHelper.MidiEventType.ProgramChange:
                        case (int)MidiHelper.MidiEventType.AfterTouchChannel:
                        case (int)MidiHelper.MidiEventType.SongSelect:
                        case (int)MidiHelper.MidiEventType.BusSelect:
                            shortMessage = new ShortMessage();
                            shortMessage.SetMessage(statusByte, din.ReadByte(), 0);
                            runningStatus = statusByte;
                            break;

                        case (int)MidiHelper.MidiEventType.TuneRequest:
                        case (int)MidiHelper.MidiEventType.EndOfExclusive:
                        case (int)MidiHelper.MidiEventType.Clock:
                        case (int)MidiHelper.MidiEventType.Start:
                        case (int)MidiHelper.MidiEventType.Continue:
                        case (int)MidiHelper.MidiEventType.Stop:
                        case (int)MidiHelper.MidiEventType.ActiveSensing:
                        case (int)MidiHelper.MidiEventType.SystemReset:
                            shortMessage = new ShortMessage();
                            shortMessage.SetMessage(statusByte, 0, 0);
                            runningStatus = statusByte;
                            break;

                        default:
                            if (runningStatus != -1)
                            {
                                switch (runningStatus & 0xF0)
                                {
                                case (int)MidiHelper.MidiEventType.NoteOff:
                                case (int)MidiHelper.MidiEventType.NoteOn:
                                case (int)MidiHelper.MidiEventType.AfterTouchPoly:
                                case (int)MidiHelper.MidiEventType.ControlChange:
                                case (int)MidiHelper.MidiEventType.PitchBend:
                                case (int)MidiHelper.MidiEventType.SongPosition:
                                    shortMessage = new ShortMessage();
                                    shortMessage.SetMessage(runningStatus, statusByte, din.ReadByte());
                                    break;

                                case (int)MidiHelper.MidiEventType.ProgramChange:
                                case (int)MidiHelper.MidiEventType.AfterTouchChannel:
                                case (int)MidiHelper.MidiEventType.SongSelect:
                                case (int)MidiHelper.MidiEventType.BusSelect:
                                    shortMessage = new ShortMessage();
                                    shortMessage.SetMessage(runningStatus, statusByte, 0);
                                    continue;

                                case (int)MidiHelper.MidiEventType.TuneRequest:
                                case (int)MidiHelper.MidiEventType.EndOfExclusive:
                                case (int)MidiHelper.MidiEventType.Clock:
                                case (int)MidiHelper.MidiEventType.Start:
                                case (int)MidiHelper.MidiEventType.Continue:
                                case (int)MidiHelper.MidiEventType.Stop:
                                case (int)MidiHelper.MidiEventType.ActiveSensing:
                                case (int)MidiHelper.MidiEventType.SystemReset:
                                    shortMessage = new ShortMessage();
                                    shortMessage.SetMessage(runningStatus, 0, 0);
                                    continue;

                                default:
                                    throw new InvalidMidiDataException("Invalid Short MIDI Event: " + statusByte);
                                }
                            }
                            else
                            {
                                throw new InvalidMidiDataException("Invalid Short MIDI Event: " + statusByte);
                            }

                            break;
                        }
                        mm = shortMessage;
                    }
                    else if (statusByte == (int)MidiHelper.MidiEventType.SystemExclusive ||
                             statusByte == (int)MidiHelper.MidiEventType.EndOfExclusive)
                    {
                        // System Exclusive event
                        int sysexLength  = din.ReadVariableLengthInt();
                        var sysexData    = din.ReadBytes(sysexLength);
                        var sysexMessage = new SysexMessage();
                        sysexMessage.SetMessage(statusByte, sysexData, sysexLength);
                        mm            = sysexMessage;
                        runningStatus = -1;
                    }
                    else if (statusByte == (int)MidiHelper.META)
                    {
                        // Meta Message
                        byte metaType    = din.ReadByte();
                        int  metaLength  = din.ReadVariableLengthInt();
                        var  metaData    = din.ReadBytes(metaLength);
                        var  metaMessage = new MetaMessage();
                        metaMessage.SetMessage(metaType, metaData, metaLength);
                        mm = metaMessage;

                        // End of Track
                        if (metaType == (byte)MidiHelper.MetaEventType.EndOfTrack)
                        {
                            done = true;
                        }

                        runningStatus = -1;
                    }
                    else
                    {
                        throw new InvalidMidiDataException("Invalid status byte: " + statusByte);
                    }

                    track.Add(new MidiEvent(mm, click));
                }
            }

            return(seq);
        }