private int CompareSimpleMidi(SimpleMidiMessage lhs, SimpleMidiMessage rhs) { int first = lhs.Timestamp.CompareTo(rhs.Timestamp); if (first != 0) { return(first); } int lhsType = (lhs.Data & 0xf0) >> 4; int rhsType = (rhs.Data & 0xf0) >> 4; int second = lhsType.CompareTo(rhsType); return(second); }
/// <summary> /// Determines whether this instance and another specified <see cref="SimpleMidiMessage"/> object have the same value. /// </summary> /// <param name="other">The <see cref="SimpleMidiMessage"/> to compare with the current instance. </param> /// <returns> /// true if <paramref name="other"/> and this instance represent the same value; otherwise, false. /// </returns> public bool Equals(SimpleMidiMessage other) { return(Timestamp.Equals(other.Timestamp) && Data == other.Data); }
/// <summary> /// Returns the next simple midi event to be played from the queue. /// It can either block it until it is time to actually play it, or return the current timestamp immediately. /// </summary> /// <param name="block">Force the BeatScheduler to return immediately</param> /// <returns>A simple MIDI event and a timestamp. If nothing exists in the queue, it either /// returns an empty message or blocks until one is available.</returns> public SimpleMidiMessage GetNextMidiCommand(bool block = true) { //Try to find a new tone 10 times. Should only run once in most conditions, but //we need recycle our wait if the queue gets new things added while we wait. //could be while(true) but this way we don't risk an infinite loop //which is bad. //Probably also possible to do a simpler reset but cannot quite see how for (int i = 0; i < 10; i++) { double nextTime; lock (_syncRoot) { nextTime = _channelAllocator.NextTimeStamp; } if (nextTime == ChannelAllocator.NoMessageTime) { if (block) { _newDataAdded.WaitOne(); continue; } else { return(EmptyMessage); } } //If we were not interrupted, we assume we arrived in time //Console.Write($"{!block} || {GetWaitTimeMs(_channelAllocator.NextTimeStamp):D4} ~ "); //If not set to block or if no new data arrives if (!block || !_newDataAdded.WaitOne(GetWaitTimeMs(_channelAllocator.NextTimeStamp))) { SimpleMidiMessage message = _channelAllocator.GetNext(); //Console.WriteLine($"Fin {message}"); if (_channelAllocator.Empty) { //If the emptyHandle is not set, notify that we have finished everything if (!_emptyHandle.WaitOne(0)) { _emptyHandle.Set(); } } return(message); } } //If working in debug mode knowing that something went wrong is probably preferable //but in release we would just as well like it failing silently //This being only a single MIDI event it would not impact the overall piece overmuch #if DEBUG throw new TimeoutException("Unable to return anything after too many iterupts. This should (probably) never happen"); #else return(new SimpleMidiMessage(0, 0)); #endif }