// Play all events at a given time, return time of closest next event private uint PlayEventsAtCurrentTime(uint time) { uint nextTime = uint.MaxValue; // Play all events at the current time for (; (curIndex < events.Length) && (events[curIndex].TrackTime <= time); curIndex++) { // Play this event! ISequencerMessage message = events[curIndex].SequencerMessage; // If this is a meta sequencer message, it affects the player itself if (message is ISequencerMetaMessage) { // Process meta-messages locally ApplyMetaMessage(events[curIndex], (ISequencerMetaMessage)message); } // Notify listeners if (OnSequencerEventPlayed != null) { SequencerEventArg arg = new SequencerEventArg(SequencerEventArg.EType.Play, events[curIndex]); OnSequencerEventPlayed(this, arg); } } // End of sequence if (curIndex == events.Length) { // Notify listeners if (OnSequencerEventPlayed != null) { SequencerEventArg arg = new SequencerEventArg(SequencerEventArg.EType.End, null); OnSequencerEventPlayed(this, arg); } playing = false; nextTime = 0; } else { nextTime = events[curIndex].TrackTime; } return(nextTime); }
private void Player() { uint time = 0; uint timeOfNextEvent = 0; bool firstTime = true; while (!closing) { // Wait to be told to do something if (!playing && !closing && !firstTime) { lock (playerRequest) { Monitor.Wait(playerRequest); } } firstTime = false; // Reset to specified point in time if requested if (positionToTime != uint.MaxValue) { time = positionToTime; timeOfNextEvent = PositionCurIndexToTime(positionToTime); positionToTime = uint.MaxValue; // Play all events at time 0 (tempo, key sig, ...) if (time == 0) { timeOfNextEvent = PlayEventsAtCurrentTime(time); } continue; } // Remember current time SetupTimeReference(time); // Play! while (playing) { inPlayingLoop = true; // Compute current time (from start of play) in usecs ulong now = hrc.GetElapsedInMicroSeconds(t0Tick); // Compute time of next midi event in usecs ulong timeOfNextEventInMicroSeconds = MidiTimeToMicroSeconds(timeOfNextEvent - t0Midi); // Decide whether to wait, yield or play ulong delta = (timeOfNextEventInMicroSeconds > now) ? (timeOfNextEventInMicroSeconds - now) : 0; if (delta > 2000) { Thread.Sleep((int)delta / 2000); continue; } if (delta > 0) { Thread.Yield(); continue; } // Compute new midi time time = t0Midi + MicroSecondsToMidiTime(now); // Play all events at current time timeOfNextEvent = PlayEventsAtCurrentTime(time); } inPlayingLoop = false; timeWhenStopped = timeOfNextEvent; SequencerEventArg arg = new SequencerEventArg(SequencerEventArg.EType.Reset, null); OnSequencerEventPlayed(this, arg); } }