Timers - operatortwo/Mmultitool GitHub Wiki
Two timers
There are two Timers in the application, one for the player and one for refreshing controls on the UserInterface (UI)
Timer for Player
Is located in the Mmultitool library and is responsible for the exact timing of the MIDI events to be played. Since this timer runs at a high frequency, it places a certain burden on the system resources. As a compromise, the interval is set to 3 milliseconds instead of the maximum possible interval of 1 millisecond.
The timer tick serves two time bases, one for the TrackPlayer and the other for the SequencePlayer.
Please note that MIDI output from the library is handled using RaiseEvent. This separates the library from the application. The application only needs to handle the library's events and isn't tied to a specific MIDI IO.
Note Off Processing
The player contains a NoteOff processing. This means that the NotOff events in the event list are ignored. Instead, the note durations are used. Of course, the exact and complete sending of NoteOff events is very important, since missing NoteOffs or retriggering of running notes can cause problems in the sound generator.
As you can see in the Player Timer flowchart, Do_TimedNoteOff is always called first. This checks for expired notes, raises the corresponding NoteOff events and and removes the NoteOff data from the NoteOffListCollection.
When a NoteOn event occurs, the system first checks whether the note is still playing.
If so, a NoteOff event is raised, and the NoteOff data is removed from the NoteOffListCollection.
Then, the NoteOn event for the new note is raised, and the NoteOff data is inserted into the NoteOffListCollection using the NoteDuration.
If the NoteOff list is full, a NoteOff event is raised for the oldest note and the entry is removed. The NoteOff list currently contains 16 channels x 32 note entries, where a note entry consists of UInterger, Byte, Byte, Byte, which results in an approximate size of 4 Kb.
When the player is stopped or the play position is changed, AllRunningNotesOff is called, which raises all outstanding NoteOff events and empties the NoteOffListCollection.
Timer for Screen Refresh
Located in the application, not in the library. The interval is set to 50 milliseconds, so it is executed about 20 times per second. This timer is only needed by the user interface (UI). The player runs independently, although it provides some notifications for the UI.
An example of a UI control is the player position display. Updating via the player would be a drain on system resources and unnecessary. A slower update via screen refresh makes sense.
For larger controls like TrackView, querying 'IsVisible' is useful. This can save a lot of effort, since only visible controls need to be updated.