/// <summary> /// Creates a new instance with the specified tempo /// </summary> /// <param name="tempo">The tempo</param> public MidiMessageMetaTempo(double tempo) : this(MidiUtility.TempoToMicroTempo(tempo)) { }
/// <summary> /// Adjusts the tempo of a MIDI file /// </summary> /// <param name="tempo">The new tempo</param> /// <returns>A new file with an adjusted tempo. All other tempo messages are adjusted relatively to the first one</returns> public MidiFile AdjustTempo(double tempo) => AdjustTempo(MidiUtility.TempoToMicroTempo(tempo));
/// <summary> /// Plays the sequence to the specified MIDI device using the specified timebase /// </summary> /// <param name="timeBase">The timebase to use, in pulses/ticks per quarter note</param> /// <param name="deviceIndex">The MIDI device to output to</param> /// <param name="loop">Indicates whether to loop playback or not</param> public void Preview(short timeBase = 480, int deviceIndex = 0, bool loop = false) { var handle = MidiUtility.OpenOutputDevice(deviceIndex); var ppq = timeBase; var mt = MidiUtility.TempoToMicroTempo(120d); try { while (loop) { var ticksusec = mt / (double)timeBase; var tickspertick = ticksusec / (TimeSpan.TicksPerMillisecond / 1000) * 100; var tickStart = MidiUtility.PreciseUtcNowTicks; var tickCurrent = tickStart; var end = (long)(Length * tickspertick + tickStart); var tpm = TimeSpan.TicksPerMillisecond; using (var e = AbsoluteEvents.GetEnumerator()) { if (!e.MoveNext()) { return; } var done = false; while (!done && tickCurrent <= end) { tickCurrent = MidiUtility.PreciseUtcNowTicks; var ce = (long)((tickCurrent - tickStart) / tickspertick); while (!done && e.Current.Position <= ce) { if (0xFF == e.Current.Message.Status) { var mbs = e.Current.Message as MidiMessageMeta; if (0x51 == mbs.Data1) { if (BitConverter.IsLittleEndian) { mt = (mbs.Data[0] << 16) | (mbs.Data[1] << 8) | mbs.Data[2]; } else { mt = (mbs.Data[2] << 16) | (mbs.Data[1] << 8) | mbs.Data[0]; } ticksusec = mt / (double)ppq; tickspertick = ticksusec / (tpm / 1000) * 100; end = (long)(Length * tickspertick + tickStart); } else if (0x2F == mbs.Data1) { done = true; } } MidiUtility.Send(handle, e.Current.Message); if (!e.MoveNext()) { done = true; } } } } } } finally { MidiUtility.CloseOutputDevice(handle); } }