Esempio n. 1
0
 public MidiMetaTextMessage(MidiMetaType type, byte[] data)
     : base(type, data)
 {
     Contract.Requires(data != null);
     Contract.Requires(data.Length > 0);
     ThrowIfMetaTypeIsNotText(type);
 }
Esempio n. 2
0
 /// <summary>
 /// Constructs a new instance.
 /// </summary>
 /// <param name="type">The type of meta message.</param>
 /// <param name="data">The data for the meta message.</param>
 public MidiMetaTextMessage(MidiMetaType type, byte[] data)
     : base(type, data)
 {
     Check.IfArgumentNull(data, nameof(data));
     Check.IfArgumentOutOfRange(data.Length, 1, int.MaxValue, nameof(data));
     ThrowIfMetaTypeIsNotText(type);
 }
Esempio n. 3
0
        /// <summary>
        /// Get the MIDI's duration in microseconds.
        /// </summary>
        public double GetDurationInMicroseconds()
        {
            double microsecondsPerTick = this.getMicrosecondsPerTick();
            ushort division            = (ushort)this.music.DeltaTimeSpec;
            double currentTempo        = MidiUtil.MIDI_DEFAULT_TEMPO;
            double midiMusicTimeLength = 0d;

            foreach (MidiTrack midiTrack in this.music.Tracks)
            {
                double trackTimeLength = 0d;
                foreach (MidiMessage midiMessage in midiTrack.Messages)
                {
                    trackTimeLength += midiMessage.DeltaTime * microsecondsPerTick;
                    MidiEvent midiEvent = midiMessage.Event;

                    if (midiEvent.EventType == MidiEvent.Meta && midiEvent.MetaType == MidiMetaType.Tempo)
                    {
                        currentTempo        = MidiMetaType.GetTempo(midiEvent.Data);
                        microsecondsPerTick = currentTempo / division;
                    }
                }

                if (trackTimeLength > midiMusicTimeLength)
                {
                    midiMusicTimeLength = trackTimeLength;
                }
            }
            return(midiMusicTimeLength);
        }
Esempio n. 4
0
        /// <summary>
        /// Returns the exact tick at the time within a MIDI track.
        /// </summary>
        /// <param name="track">The MIDI track</param>
        /// <param name="time">The time in microseconds.</param>
        /// <param name="microsecondsPerTick">The microSeconds per tick of the MIDI file.</param>
        /// <returns></returns>
        private int microsecondsToTicks(MidiTrack track, double time, double microsecondsPerTick)
        {
            ushort division           = (ushort)this.music.DeltaTimeSpec;
            double currentTempo       = MidiUtil.MIDI_DEFAULT_TEMPO;
            int    passedTicks        = 0;
            double passedMicroSeconds = 0d;

            foreach (MidiMessage midiMessage in track.Messages)
            {
                passedMicroSeconds += midiMessage.DeltaTime * microsecondsPerTick;
                passedTicks        += midiMessage.DeltaTime;
                MidiEvent midiEvent = midiMessage.Event;

                if (passedMicroSeconds > time)
                {
                    // if we overstepped the set time get the time between this message and the previous one
                    double prevMsgTime = passedMicroSeconds - midiMessage.DeltaTime * microsecondsPerTick;
                    return((int)((time - prevMsgTime) / microsecondsPerTick));
                }

                if (midiEvent.EventType == MidiEvent.Meta && midiEvent.MetaType == MidiMetaType.Tempo)
                {
                    currentTempo        = MidiMetaType.GetTempo(midiEvent.Data);
                    microsecondsPerTick = currentTempo / division;
                }
            }
            return(passedTicks);
        }
Esempio n. 5
0
        /// <summary>
        /// Constructs a new instance.
        /// </summary>
        /// <param name="type">The type of meta message.</param>
        /// <param name="data">The data for the meta message.</param>
        public MidiMetaMessage(MidiMetaType type, byte[] data)
        {
            Check.IfArgumentNull(data, nameof(data));

            MetaType = type;
            SetData(data);
        }
Esempio n. 6
0
 /// <summary>
 /// Throws an <see cref="ArgumentException"/> when the meta type is not Text.
 /// </summary>
 /// <param name="type">The meta type.</param>
 /// <exception cref="ArgumentException">Thrown when the <paramref name="type"/> is not Text.</exception>
 private static void ThrowIfMetaTypeIsNotText(MidiMetaType type)
 {
     if (!IsMetaTextType(type))
     {
         throw new ArgumentException("The MidiMetaType specified is not of a Text message.");
     }
 }
Esempio n. 7
0
        /// <summary>
        /// Constructs a new instance.
        /// </summary>
        /// <param name="type">The type of meta message.</param>
        /// <param name="text">The text for the meta message.</param>
        public MidiMetaTextMessage(MidiMetaType type, string text)
            : base(type)
        {
            Check.IfArgumentNullOrEmpty(text, nameof(text));
            ThrowIfMetaTypeIsNotText(type);

            SetData(Encoding.UTF7.GetBytes(text));
        }
Esempio n. 8
0
        public MidiMetaMessage(MidiMetaType type, byte[] data)
        {
            Contract.Requires(data != null);
            Check.IfArgumentNull(data, "data");

            this.MetaType = type;
            SetData(data);
        }
Esempio n. 9
0
        public MidiMetaTextMessage(MidiMetaType type, string text)
            : base(type)
        {
            Contract.Requires(text != null);
            Contract.Requires(text.Length > 0);
            Check.IfArgumentNull(text, "text");
            ThrowIfMetaTypeIsNotText(type);

            SetData(Encoding.UTF7.GetBytes(text));
        }
Esempio n. 10
0
        /// <summary>
        /// Creates a new Meta midi message object.
        /// </summary>
        /// <param name="metaType">The type of meta message.</param>
        /// <param name="longData">The data of the meta message. Must not be null or empty.</param>
        /// <returns>Never returns null.</returns>
        /// <remarks>The Meta message objects are NOT pooled.
        /// For some <paramref name="metaType"/> value a <see cref="MidiMetaTextMessage"/>
        /// instance is returned.</remarks>
        public MidiMetaMessage CreateMetaMessage(MidiMetaType metaType, byte[] longData)
        {
            Check.IfArgumentNull(longData, nameof(longData));

            var buffer = CopyBuffer(longData);

            if (MidiMetaTextMessage.IsMetaTextType(metaType))
            {
                return(new MidiMetaTextMessage(metaType, buffer));
            }

            return(new MidiMetaMessage(metaType, buffer));
        }
Esempio n. 11
0
        public MidiMetaMessage CreateMetaMessage(MidiMetaType metaType, byte[] longData)
        {
            Contract.Requires(metaType != MidiMetaType.Unknown);
            Contract.Requires(longData != null);
            Contract.Ensures(Contract.Result <MidiMetaMessage>() != null);
            Check.IfArgumentNull(longData, "longData");

            var buffer = this.CopyBuffer(longData);

            if (MidiMetaTextMessage.IsMetaTextType(metaType))
            {
                return(new MidiMetaTextMessage(metaType, buffer));
            }

            return(new MidiMetaMessage(metaType, buffer));
        }
Esempio n. 12
0
        public static MetaMidiEvent ParseMetaEvent(Stream inputStream, int deltaTime, byte metaTypeCode)
        {
            MidiMetaType metaType = (MidiMetaType)metaTypeCode;

            switch (metaType)
            {
            case MidiMetaType.SequenceNumber:
                return(SequenceNumberMetaMidiEvent.ParseSequenceNumberMetaMidiEvent(inputStream, deltaTime));

            case MidiMetaType.Text:
            case MidiMetaType.CopyrightNotice:
            case MidiMetaType.SeqTrackName:
            case MidiMetaType.InstrumentName:
            case MidiMetaType.Lyric:
            case MidiMetaType.Marker:
            case MidiMetaType.CuePoint:
                return(TextMetaMidiEvent.ParseTextMetaMidiEvent(inputStream, deltaTime, metaTypeCode));

            case MidiMetaType.ChannelPrefix:
                return(ChannelPrefixMetaMidiEvent.ParseChannelPrefixMetaMidiEvent(inputStream, deltaTime));

            case MidiMetaType.EndOfTrack:
                return(EndOfTrackMetaMidiEvent.ParseEndOfTrackMetaMidiEvent(inputStream, deltaTime));

            case MidiMetaType.SetTempo:
                return(SetTempoMetaMidiEvent.ParseSetTempoMetaMidiEvent(inputStream, deltaTime));

            case MidiMetaType.SMTPEOffset:
                return(SMTPEOffsetMetaMidiEvent.ParseSMTPEOffsetMetaMidiEvent(inputStream, deltaTime));

            case MidiMetaType.TimeSignature:
                return(TimeSignatureMetaMidiEvent.ParseTimeSignatureMetaMidiEvent(inputStream, deltaTime));

            case MidiMetaType.KeySignature:
                return(KeySignatureMetaMidiEvent.ParseKeySignatureMetaMidiEvent(inputStream, deltaTime));

            case MidiMetaType.SequencerSpecific:
                return(SequencerSpecificMetaMidiEvent.ParseSequencerSpecificMetaMidiEvent(inputStream, deltaTime));

            default:
                Debug.Log($"Encountered Unknown Meta Midi Event: {metaTypeCode:X2}");
                return(UnknownMetaMidiEvent.ParseUnknownMetaMidiEvent(inputStream, deltaTime, metaTypeCode));
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Writes a meta event to the stream.
        /// </summary>
        /// <param name="deltaTime">Must be greater or equal to zero.</param>
        /// <param name="type">The type of meta event.</param>
        /// <param name="data">The data for the meta event. Must not be null.</param>
        public void WriteMetaEvent(long deltaTime, MidiMetaType type, byte[] data)
        {
            Check.IfArgumentNull(data, nameof(data));
            Check.IfArgumentOutOfRange(deltaTime, 0, uint.MaxValue, nameof(deltaTime));
            _lastStatus = 0;

            WriteVariableLength((uint)deltaTime);

            // meta data marker
            _writer.Write((byte)0xFF);

            // meta type
            _writer.Write((byte)type);

            // length of data
            WriteVariableLength((uint)data.Length);

            // meta data
            _writer.Write(data);
        }
Esempio n. 14
0
        public void WriteMetaEvent(long deltaTime, MidiMetaType type, byte[] data)
        {
            Check.IfArgumentNull(data, "data");
            Check.IfArgumentOutOfRange(deltaTime, 0, uint.MaxValue, "deltaTime");
            this.lastStatus = 0;

            this.WriteVariableLength((uint)deltaTime);

            // meta data marker
            this.writer.Write((byte)0xFF);

            // meta type
            this.writer.Write((byte)type);

            // length of data
            this.WriteVariableLength((uint)data.Length);

            // meta data
            this.writer.Write(data);
        }
Esempio n. 15
0
        /// <summary>
        /// Returns true when the <paramref name="type"/> is Text.
        /// </summary>
        /// <param name="type">The meta type.</param>
        /// <returns>Returns true if Text, otherwise false.</returns>
        public static bool IsMetaTextType(MidiMetaType type)
        {
            switch (type)
            {
            case MidiMetaType.Copyright:
            case MidiMetaType.CuePoint:
            case MidiMetaType.Custom:
            case MidiMetaType.DeviceName:
            case MidiMetaType.Instrument:
            case MidiMetaType.Lyric:
            case MidiMetaType.Marker:
            case MidiMetaType.PatchName:
            case MidiMetaType.Text:
            case MidiMetaType.TrackName:
                return(true);

            default:
                return(false);
            }
        }
Esempio n. 16
0
 /// <summary>
 /// For derived classes.
 /// </summary>
 /// <param name="type">The type of meta message.</param>
 protected MidiMetaMessage(MidiMetaType type)
 {
     MetaType = type;
 }
Esempio n. 17
0
 public void GetTempo()
 {
     Assert.AreEqual(500000, MidiMetaType.GetTempo(new byte[] { 7, 0xA1, 0x20 }, 0), "500000");
 }
Esempio n. 18
0
 public void GetBpm()
 {
     Assert.AreEqual(120, MidiMetaType.GetBpm(new byte[] { 7, 0xA1, 0x20 }, 0), "120");
     Assert.AreEqual(140, Math.Round(MidiMetaType.GetBpm(new byte[] { 6, 0x8A, 0xB1 }, 0)), "140");
 }
Esempio n. 19
0
    private double GetTimeLengthInMicroseconds(MidiMusic midiMusic)
    {
        ushort       division            = (ushort)midiMusic.DeltaTimeSpec;
        const double defaultTempo        = 500000; // in microseconds per quarter-note, equals 120 beats per minute => 500000 / 1000000 * 4 * 60 = 120
        double       currentTempo        = defaultTempo;
        double       microsecondsPerTick = 0d;

        // division = 59512;

        Debug.Log("Divisions: " + System.Convert.ToString(division, 2).PadLeft(16, '0'));

        if (division >> 15 == 0)
        {
            Debug.Log("MSB is 0");

            microsecondsPerTick = currentTempo / division;
            // Debug.Log("MicrosecondsPerTick: " + microsecondsPerTick);
        }
        else
        {
            Debug.Log("MSB is 1");

            byte bitmask = 255; // 1111_1111
            byte bits    = (byte)((division >> 8) & bitmask);
            byte negatedFramesPerSecond = (byte)~bits;
            byte framesPerSecond        = (byte)(negatedFramesPerSecond + 1);
            Debug.Log("framesPerSecond: " + framesPerSecond);

            byte ticksPerFrame = (byte)(division & bitmask);
            Debug.Log("ticksPerFrame: " + System.Convert.ToString(ticksPerFrame, 2));
            Debug.Log("ticksPerFrame: " + ticksPerFrame);

            double ticksPerSecond = ticksPerFrame * framesPerSecond;
            microsecondsPerTick = 1000000 / ticksPerSecond;
        }

        double midiMusicTimeLength = 0d;

        foreach (MidiTrack midiTrack in midiMusic.Tracks)
        {
            double trackTimeLength = 0d;

            foreach (MidiMessage midiMessage in midiTrack.Messages)
            {
                trackTimeLength += midiMessage.DeltaTime * microsecondsPerTick;
                MidiEvent midiEvent = midiMessage.Event;

                if (midiEvent.EventType == MidiEvent.Meta && midiEvent.MetaType == MidiMetaType.Tempo)
                {
                    currentTempo        = MidiMetaType.GetTempo(midiEvent.Data);
                    microsecondsPerTick = currentTempo / division;
                }
            }

            if (trackTimeLength > midiMusicTimeLength)
            {
                midiMusicTimeLength = trackTimeLength;
            }
        }

        return(midiMusicTimeLength);
    }