/// <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> /// 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); }
public void GetTempo() { Assert.AreEqual(500000, MidiMetaType.GetTempo(new byte[] { 7, 0xA1, 0x20 }, 0), "500000"); }
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); }