These are hexadecimal numbers, a representation of the 2 bytes that make up a Program Change message. All of the meanings are available in this summary of all MIDI messages: Summary of MIDI 1.0 Messages (represented in binary numbers)
There’s some online converters you can find that can help convert between hexadecimal, decimal and binary.
Let’s decode what the two bytes c5 21 actually mean in MIDI:
- First convert to binary: c5 → 11000101, 21 → 00100001
- The first 4 bits (1100) of the first byte is the type of the message, it matches this entry in the summary table:
As explained near the top of the table, ‘nnnn’ bits represent the channel of the MIDI message. In this case, ‘0101’ is decimal 5. By convention, MIDI channels are represented to the users in the range 1 - 16, but the ‘nnnn’ part represents a number in the 0 - 15 range. That means we have to add 1 to shift the value into the one presented to the users, so the actual channel of this message is 6.
- The 2nd byte must have the very first bit to be 0, and the remaining 7 bits (‘ppppppp’) is the program number. ‘0100001’ converted to decimal is 33, so the program change number should be 33. It is not very strictly defined whether the program numbers should be in the range 0-127 (matching the exact decimal representation), or 1 - 128 (shifted by 1, as MIDI Channel numbers are), If two devices use a different display convention, they’ll be off by one.
All that said, you may let Midihub Editor do the hard work of decoding the messages, by disabling the ‘Raw Display’ mode in the Settings menu.
The reason the program change numbers differ between devices could be the different convention of the program number display (0 - 127 vs 1 - 128). Still, all of the program numbers can be addressed by either device, you should just be aware of the ‘off by one’ situation. You could try and determine the lowest or highest number of the program on each device, and if they don’t align, you can confirm that they’re based on different conventions.