That's the trap I'm in, yes. MIDI events are acted on immediately.Nasta wrote: Thu Aug 21, 2025 5:08 pm MIDI is a 'bit' different, in that it can be used as an 'immediate event' serial stream - a 'note on' code received is immediately played.
A MIDI file measures time in ticks. The file contains a header that establishes the speed of the music, and configures how many ticks divide up a quarter note. This is a Tempo metadata event. Next it sets up Time signature event, eg: 3/4, 4/4, 7/4* etc.
The playing of the file first configures the tick rate, then retrieves MIDI groups from the file. A note or action (master volume, key velocity, various effects or etc) can contain several bytes establishing the note, how and where it is to be played. Actions that happen simultaneously are grouped together. Subsequent events are indicated by the number of ticks separating the events.
A MIDI beat clock is used to synchronize multiple MIDI instruments. This is 24 ticks per quarter note. 96 ticks per beat. 384 ticks per 4-beat bar. At 120 beats per minute that's 192 ticks per second. Anyone who's used a digital logic analyser knows you need to have at least 4-5x the frequency as your sample rate to the fundamental frequency of your sampled signal. This is true in the inverse. A 192 Hz ticker suggests a 960 Hz service interval in a system where other services also make time demands. Faster is better, to a point. Allowing for the music playback and screen updates to scroll displayed music/patterns, plus other events like capturing external MIDI, keypresses simulating keyboard inputs, etc. all need to be serviced in priority order during the timeslice. If time runs out and the next tick occurs before everything's done, the lowest priority elements - anything non-playback or composition related - need load shedding. Thus a new tick with events the events happen first. If there are no events in the period - which is known ahead of time because we can see the future - we can do the more mundane tasks like updating the sequencer display, etc.
With this background, a 50 Hz poll that's also doing other things is insufficient. A fixed fast interrupt may or may not be appropriate. That is affected by many factors: CPU/bus speed, tick frequency, how much MIDI data you can transfer within a tick**, etc. The last item becomes an issue because situations arise where I may need to play notes to gthe MIDI device while also checking MIDI IN and parsing that to see if it needs to be directly retransmitted for live playback, or live plus record data to timeline, or if the packet bytes are non-audio data (config/tick/etc.)...
So here I am working out a programmable interrupt timer that's simple to implement, use, and is flexible enough to meet more than just my own needs.
* Solsbury Hill by Peter Gabriel is a really great example of 7/4 time. Catchy and fun. Give it a listen and get a feel for how it throws you off-kilter to match the theme of the song. Most people have a sense of being unsettled but can't put their finger on why.
** MIDI serial runs at 31250 bps, with 8 bit data start and stop bits. This gives a theoretical 3125 bytes/second. The average playback MIDI message is 3 bytes. Typical peak throughput on serial MIDI is..... 960 characters per second. 1.042 milliseconds per byte or 3.126 milliseconds per typical note. In this environment, +/-20 ms is a 3 tick range, and +/- 70ms is 10 ticks. Our ears can hear that. We determine sound direction using sub-1 millisecond phase shifts. Ears are amazing!