I’ve spent some time with the NRPN and SysEx the past six months or so. There are lots of issues there. I just didn’t think there was a need to list them because I figured Holger would find them anyway. But since it came up, I can add some info.
The NRPN values that the Solaris sends out don’t correspond to the values you see in the UI or would expect to get. Instead, the range of the parameter is spread out over the total 14-bit range available. So for example, OSC fine tune has a range of 200 (-100 to +100). That divides the full range of 14-bit NRPN which is 16384. This means that for fine tune each step is roughly 82, with zero being at 8192. Since different parameters have different ranges, the step size will be different for each parameter. If you were to receive 9591 the fine tune would then be +18. Although this is not ideally how you’d like to see the values, it might be livable if you knew exactly the calculations done internally. But I think due to round-off error when dividing, it’s not always easy get from the NRPN value to the same value Solaris is displaying.
For the arp editor I was able to do it because there were only a handful of parameters and I spent some time adjusting to get them right. But I didn’t want to do that for 1000+ parameters in my other programs. So instead I don’t interpret the NRPN values. Instead I use SysEx because the SysEx values are easier to interpret and are not the same as NRPN. So whenever I receive an NRPN value, I ignore that value and then send a SysEx request for the same parameter and use the value I get from SysEx. (Actually I wait about 300ms for NRPN activity to settle down before requesting the SysEx value.) So I haven’t spent as much time with NRPN since SysEx values seem more reliable to me.
With SysEx there seem to be two types of parameters. I call them numerical and enumerations (or lists). Numerical values are just the values you would expect. For example if the OSC fine tune is set to +18 then you will receive value 18. Keep in mind these values are signed. (Using a 16-bit int I shift the value left by 2 to pick up the sign and then shift back 2 right.) Enumeration values are for parameters that are lists of things, such as OSC type, wave type, modulation destinations, etc. These SysEx values need to be divided by 4 to get the true value. I don’t know why these are different but I assume it has to do with the internal implementation. As you've discovered, the value you get is not necessarily the true value multiplied by 4. For OSC MM1 you might get 4 or 5 or 6. But in any case, you divide that by 4 and you get 1 which is the index for MM1.
How do you know which parameters are numerical and which are enumerations? Trial and error, although it’s mostly what you’d expect. But behavior is not always consistent. For example you will find that EnablePart buttons are odd. To turn one ON you need to send 0. To turn one OFF you don’t send 1 or 4. You send at least 8192. I just use 16383.
The modulation amount for oscillators can be a bit tricky. You’ve noticed that for oscillators (as well as filters) there are actually two different amount values. There is one for pitch and another one for all other destinations. These are remembered so that when you switch the modulation destination between, say, pitch and shape, the different values are not lost. And, there are separate NRPN indexes for each and both are saved to a preset file. For example OSC 1 mod amount 1 uses index 1107 for pitch and index 269 for all other destinations. But notice that on the Solaris when you select Shape as the destination the amount is shown as a percent in steps of 1. But when you select LinFM as the destination the amount is shown in steps of 0.1. This means the value that the Solaris sends for SysEx index 269 has a different range depending on whether the destination is currently set to Shape or LinFM…either 200 or 2000 respectively. (No, the Solaris will not use a range of 2000 for both cases.) So you need to interpret the value you get in the context of the current destination setting. Further, you might have noticed that when you switch the destination from LinFM to Shape, the value in the Solaris gets rounded to integer so that when you switch back to LinFM you lose the decimal. An editor has to be aware of this to stay in sync with the Solaris.
Parameters that have a range of 0 to 20 seconds cannot be read correctly. Note that the increment for these time values is 0.1 ms. Given the range of 0 to 20 seconds that is 200000 steps. But the allowable range of NRPN is only 16384. So NRPN cannot currently convey these values. Currently it seems the values just keep wrapping around as they go up. In other words if you receive a value of 300, that might mean 30ms or 1.67s or 3.31s, etc. This is the same situation for some frequency values such as in the EQ. SysEx would be able to send larger values but currently does not.
Many parameters are not supported, or at least the NRPN indexes are not documented. Examples: transpose, FX channel info, outputs 3 thru 8 and S/PDIF, play mode, univoice, unitune, BPM, note priority, preset name, and more.
There’s more but I don’t want to dump too much. The Solaris sounds and plays great regardless!
Jim