There is provision in the MIDI Standard to send & receive microtuning, both as entire data dumps & some realtime modifications, using SysEx messages.
7EH 08 nn is MIDI Tuning Standard (Non-Real Time) &
7FH 08 nn is MIDI Tuning Standard (Real Time)
I have never personally used either of these, though I knew of their existence - so some further research may be required to see exactly how they are implemented.
The Raw spec is available from the MIDI Association : Universal System Exclusive Messages & there is a Wikipedia article on it : MIDI Tuning Standard
Further research would appear to show that some instruments - specifically Yamaha, that's where I used to work so still have people I can ask, but a Google search shows some Roland devices as also being capable - use Scale/Octave Tuning Adjust from the GM2 General MIDI 2 spec.
This is capable of adjusting each of the 12 notes in any octave by cent steps, but is repeated the same for each octave.
I found this data guide from a Roland manual
❍Scale/Octave Tuning Adjust
Status Data byte Status
F0H 7EH, 7FH, 08H, 08H, ffH, ggH, hhH, ssH... F7H
Byte Explanation
F0H Exclusive status
7EH ID number (Universal Non-realtime Message)
7FH Device ID (Broadcast)
08H Sub ID#1 (MIDI Tuning Standard)
08H Sub ID#2 (scale/octave tuning 1-byte form)
ffH Channel/Option byte 1
bits 0 to 1 = channel 15 to 16
bit 2 to 6 = Undefined
ggH Channel byte 2
bits 0 to 6 = channel 8 to 14
hhH Channel byte 3
bits 0 to 6 = channel 1 to 7
ssH 12 byte tuning offset of 12 semitones from C to B
00H = -64 [cents]
40H = 0 [cents] (equal temperament) 7FH = +63 [cents]
F7H EOX (End Of Exclusive)
Looking at that spec it would appear too be either a subset or a stricter definition of the above-mentioned MIDI Tuning Standard.
I have managed to find a link to the entire MIDI Tuning Standard spec on Microtonal Synthesis com, but frankly I'm getting well above my pay grade on the entirety of the structure.
I'll repro it here in case of future web-rot
Formatting this was a nightmare & I'm not even going to attempt to correctly code-format it, but feel free to tweak/fix any errors found
The MIDI Tuning Standard
The MIDI Tuning Standard was ratified by the MIDI Manufacturers'
Association in January 1992. Credit should be given to Robert Rich and
Carter Scholz who wrote and lobbied for this addition to the MIDI
specification. Manufacturers have the option of supporting the tuning
standard partially or in full. It is featured on some Emu and Ensoniq
instruments. Currently they implement only the non-realtime features
of the standard.
Non-realtime messages
Request a bulk tuning dump from your synthesizer by sending the
following codes:
F0 7E id 08 00 tt F7
where
F0 7E = universal non-realtime SysEx header
id = target device ID
08 = sub-ID #1 (MIDI tuning standard)
00 = sub-ID #2 (bulk
dump request)
tt = tuning program number 0 to 127 in hexadecimal
F7 = end of SysEx message
for example, request a bulk dump of
tuning program 16 from device 1 with the following message:
F0 7E 01 08 00 10 F7
The synthesizer sends the bulk tuning dump in the
following format:
F0 7E id 08 01 tt x16 x128 ck F7
where
F0 7E = universal non-realtime
SysEx header id = target device ID
08 = sub-ID #1 (MIDI tuning standard)
01 = sub-ID #2 (Bulk dump
reply)
tt = tuning program number 0 to 127 in hexadecimal
tn =
tuning name (16 ASCII characters)
xx yy zz = frequency data for one
note (repeated 128 times)
see below for format
ck = checksum
F7 = end of SysEx message
Realtime messages
The following message changes the tuning of one or more notes in
realtime. The "preferred" method according to the specification is to
change the tuning immediately for any notes currently sounding. The
optional method is to change the tuning only for new notes that follow
the tuning message. In reality, the preferred method depends on what
the composer is trying to accomplish and this author recommends a
global parameter on the synthesizer to select between immediate and
new note only retuning.
F0 7F id 08 02 tt ll [kk xx yy zz]x(ll) F7
where
F0 7F = universal realtime SysEx header
id = target device ID
08
= sub-id #1 (MIDI tuning standard)
02 = sub-id #2 (note change)
tt = tuning program number from 0 to 127
ll = number of notes to be changed (sets of [kk xx yy zz])
[kk xx yy zz] = MIDI note number,
followed by frequency data for note
F7 = end of SysEx message
Tuning program and bank changes
Tuning programs and banks are changed using registered parameter
number controller messages.
Tuning program change
Bn 64 00 65 03 06 tt (data entry)
Bn 64 00 65 03 60 7F (data
increment)
Bn 64 00 65 03 61 7F (data decrement)
n = basic channel number
tt = tuning program number from 1 to 128
Tuning bank change
Bn 64 00 65 04 06 tt (data entry)
Bn 64 00 65 04 60 7F (data increment)
Bn 64 00 65 04 61 7F (data decrement)
n = basic channel number
tt = tuning bank number from 1 to 128
Frequency data format (all bytes in hex)
xx = semitone (MIDI note number to retune to, unit is 100 cents)
yy = MSB of fractional part (1/128 semitone = 100/128 cents = .78125 cent
units)
zz = LSB of fractional part (1/16384 semitone = 100/16384 cents
= .0061 cent units)
7F 7F 7F is reserved for no change to the existing note tuning
I also discovered Yamaha make a free iPhone/Pad app, Scale Tuner to adjust this on the fly for supported keyboards. It may work on other devices that support the same spec. It does look like it requires a hardware purchase of lightning/30-pin connector to MIDI, though I didn't track one of those down specifically.
I hope that's not considered spammy even if I did used to work there. I haven't tried it, just providing info for interested parties