implement NPRN protocl for controlling TGs with a MIDI controller #604
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Hello!
First off, I want to thank you for creating this amazing project. I found out about it on Floyd Steinberg's YouTube channel just a few days ago, and I've already started using it to make music.
I found some things were missing for my specific use-case so I had a quick couple of hours hacking away to add NRPN support to be able to control the TGs using my Arturia KeyLab 61 Mk1 MIDI controller. So this functionality is 100% working, but its implementation is a proof of concept as it uses some abusive data access shortcuts and is undocumented apart from the description I provide below.
The following CC controllers are used:
0 >= value <= 5
selects operator 1-6 parameters of the TG specified by the channel of the messagevalue == 6
selects voice parameters of the TG specified by the channel of the messagevalue > 6
is ignored0 >= value <= 22
selects what parameter to write to the TG specified by the channel of the message, for exampleDEXED_OP_EG_R1
, or one of the added parameters likeMIDI_NRPN_PROGRAM_CHANGE
.This is how I use it on my KeyLab
CC99=0...6
value, which allows me to select either an individual operator or the entire voice.CC99=127
,LSB=DEXED_OP_EG_R1
,Controller=38
. When I turn the knob the controller will send (in order)CC99=127
,CC98=DEXED_OP_EG_R1
,CC38=<value of encoder>
.As you can see, the fact that MSB
CC99=127
is ignored by MiniDexed I can effectively preselect the parameter destination for every knob and slider on my controller, achieving knob per function for an entire TG. Switching channel on my controller allows me to control any of the 8 TG's.I also added parameter scaling so each parameter is controlled by the full resolution of the 7 useful bits of the data field of the message, i.e. 0-127. The reason for this is that it's not possible to configure the range of the KeyLab's encoders when they are in NRPN mode.
Now on to the elephant in the room.
I need some guidance for how to properly implement this so it is in line with the general architecture of the code. Some thoughts I've had so far.
I'm exposing the
CDexedAdapter
pointer from theCMiniDexed
as public, this is obviously a hack. There are some functions inDexed
likeDexed::setFCcontroller
that could be exposed in theCMiniDexed
instead, but I'm not sure which one to use or how.I don't know if the parameter scaling is duplicated code, nor do I know if this is the right place to do the scaling.
There should be some degree of configurability. For example
I use a Dexed instance on my laptop to show me what's going on while I tweak the parameters. To keep the UI up to date with the TG I'm editing I'm sending an entire sysex voice dump for every parameter change, this should probably be sent as a smaller parameter change sysex according to the DX7 manual. Where should this code be placed? Or does it even exist somewhere else so I can reuse it? Should it be configurable in the minidexed.ini file?
How to deal with menu updates?
The order of the operators is reversed, setting
CC99=0
selects operator 6. This is an easy fix but should be done after fixing the architectural problems.I don't know if this PR is what the project wants. For my use case it is essential to get rid of any menu diving, I hate menu diving. If this PR is not in line with what the project wants I would still be happy to get the architectural guidance so I can get a better understanding of the code to maintain my own fork of the project.
So please, see this PR as a work in progress created to invite both philosophical and technical discussions. Or, whether or not to support NRPN at all, and how it's implementation should look like.