public MidiMetaTextMessage(MidiMetaType type, byte[] data) : base(type, data) { Contract.Requires(data != null); Contract.Requires(data.Length > 0); ThrowIfMetaTypeIsNotText(type); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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."); } }
/// <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)); }
public MidiMetaMessage(MidiMetaType type, byte[] data) { Contract.Requires(data != null); Check.IfArgumentNull(data, "data"); this.MetaType = type; SetData(data); }
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)); }
/// <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)); }
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)); }
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)); } }
/// <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); }
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); }
/// <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); } }
/// <summary> /// For derived classes. /// </summary> /// <param name="type">The type of meta message.</param> protected MidiMetaMessage(MidiMetaType type) { MetaType = type; }
public void GetTempo() { Assert.AreEqual(500000, MidiMetaType.GetTempo(new byte[] { 7, 0xA1, 0x20 }, 0), "500000"); }
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"); }
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); }