Old 12-03-2020, 05:04 AM   #201
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 10,042
Default

Quote:
Originally Posted by Talagan View Post
When I discovered the existence of high res velocity I was also surprised that it could make any difference. But it is probably useful if a precise range of samples is transformed and amplified in the MIDI chain, idk
As a Pianist using a very decent Midi keyboard (Kawai VPC 1), I would love to try higher resolution velocity. But neither the VPC 1 nor any of the plugins I use support this.

But as well the VPV1 as some Piano libraries do feature a velocity curve the allows for placing the 128 steps in different locations. But this is not very comfortable nor flexible.

-Michael
mschnell is online now   Reply With Quote
Old 12-03-2020, 07:22 AM   #202
Talagan
Human being with feelings
 
Join Date: Feb 2016
Location: Paris / France
Posts: 161
Default

Quote:
Originally Posted by mschnell View Post
Did some tests.

Did not ind out how to handle High Res CC input ?

-Michael
The high res CC input is a global setting (the trigger for global settings is the button in the bottom right of the screen, then you have a button to enable High Res MIDI input).

When that option is enabled globally, when choosing a MSB CC, it will (should) act as a high res CC input. That means, Mapper X will aggregate the MSB CC value + the counterpart LSB CC value into a floating value (the LSB counterpart is MSB + 32 when it is available). Then the curve is applied to that floating value, then, either you output it back on a low res CC or you can output as high res MIDI on a High Res capable CC (you should choose the MSB CC as output and Mapper X will output values on both MSB and LSB counterpart). To output CCs as High Res MIDI, you have to explicitly set High Res output too on the selected control. The same principles apply for velocity (but in the case of the velocity, it does not use MSB/LSB logic but CC#88 logic).

If everything goes well you should see green hints "[High Res]" labels on both input and output lines in the UI

highres.png

It can seem strange to enable high res input globally but high res output per-control, but that part was a bit hard to design correctly without having things clashing in the architecture.

(PS: the passthrough option on the screenshot is a spoiler for next version)

Last edited by Talagan; 12-03-2020 at 02:53 PM. Reason: my english sucks
Talagan is offline   Reply With Quote
Old 12-05-2020, 01:42 PM   #203
Talagan
Human being with feelings
 
Join Date: Feb 2016
Location: Paris / France
Posts: 161
Default

Hey all, V 4.2 is out through ReaPack!

For the same price, I offer you your original MIDI events.

Changelog
  • Added pass through option for every control type
  • Changed default value for the on/off transposition toggle of a keyboard range (now 'on' by default)

Install/Update notes

As usual, avoid updating MIDI CC Mapper X while having a project using an older version open. Just restart REAPER after update to take no risks.

Desc

The pass through option can be found on every control. When enabled on a control, if a MIDI event is caught by that control, MIDI CC Mapper X will re-emit the original, unmodified MIDI event that triggered the control in addition to the new, modified event.

So you can perform various kind of MIDI splits. This canonic option is available in MIDI CC Mapper (not X) and I've found it was missing.

Be careful when enabling this option : creating interferences between MIDI routes is easy, and you can do whatever-I-can't-think-about especially when trying to apply this on exotic MIDI events like polyphonic after-touch.

Last edited by Talagan; 12-06-2020 at 03:26 AM. Reason: Definitely cannot write a decent message in one shot
Talagan is offline   Reply With Quote
Old 12-06-2020, 08:10 AM   #204
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 10,042
Default

Quote:
Originally Posted by Talagan View Post
The high res CC input is a global setting (the trigger for global settings is the button in the bottom right of the screen, then you have a button to enable High Res MIDI input).
In fact I don't like that idea. IMHO, it is a rather common usage case that one CC (or Velocity) is used as hiRes, while other are low Res.

AT can be HiRes as input, but seemingly not as output ?

-Michael
mschnell is online now   Reply With Quote
Old 12-06-2020, 09:28 AM   #205
Talagan
Human being with feelings
 
Join Date: Feb 2016
Location: Paris / France
Posts: 161
Default

Quote:
Originally Posted by mschnell View Post
In fact I don't like that idea. IMHO, it is a rather common usage case that one CC (or Velocity) is used as hiRes, while other are low Res.
I still need to think about it and see if and how I can change the paradigm to avoid interferences between controls. (Ex of clashing configuration : if one enables HR on a control A set on CC#0 channel 4, and builds an other control B on CC#32 channel 4, what should the plugin do with an event on CC#32 channel 4 ? Aggregate with CC#0 for control A, pass the event to control B, or do both maybe ? - the global option has the advantage to make it clear that you can't use CC#32-63 as standalone CCs if HR is enabled... but it's a constraint. I assumed that if you had a MIDI controller that was HR capable, it would be all or nothing. Maybe false assumption !).

Note though that if you enable the option it won't prevent you from using pure low-res CCs.

And CC#0-31 will aggregate CC#32-63 but this does not change anything if CC#32-63 are not used.

Quote:
Originally Posted by mschnell View Post
AT can be HiRes as input, but seemingly not as output ?
This is a bug in the UI. It should not show "[High Res]" for AT, it's a lie I could not find any documentation about HR polyponic AT so nothing's implemented (I don't think that event exist). The same lie is displayed for Pitch Bend and needs to be corrected.

Last edited by Talagan; 12-06-2020 at 10:14 AM.
Talagan is offline   Reply With Quote
Old 12-06-2020, 03:30 PM   #206
Talagan
Human being with feelings
 
Join Date: Feb 2016
Location: Paris / France
Posts: 161
Default

@mschnell : Michael, thanks for challenging the plugin. I'm slowly (not that slowly, in fact) changing my mind after your remarks and all the work that's been done so far. After thought and inspection, having the HR input option per-control fits the current architecture of the plugin and feels more natural. Of course, a user can always mess up his/her configuration and create clashing MIDI routes but hey this is life with funny and not painful errors. I'm more and more convinced so I'll prepare a V4.3 embedding those changes.
Talagan is offline   Reply With Quote
Old 12-06-2020, 03:41 PM   #207
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 10,042
Default

Quote:
Originally Posted by Talagan View Post
I still need to think about it
In my recent JSFXes I used a very simple approach:

In a drop-down control (e.g. appropriately configured Slider) allow for selecting CC# as

0...127, 0HR ..31 HR, AT. All with appropriate names.
seems straight forwarded to me.
-Michael
mschnell is online now   Reply With Quote
Old 12-07-2020, 02:41 PM   #208
Talagan
Human being with feelings
 
Join Date: Feb 2016
Location: Paris / France
Posts: 161
Default

Quote:
Originally Posted by mschnell View Post
In my recent JSFXes I used a very simple approach:

In a drop-down control (e.g. appropriately configured Slider) allow for selecting CC# as

0...127, 0HR ..31 HR, AT. All with appropriate names.
seems straight forwarded to me.
-Michael
Yes, I do agree. It's a nice approach. I already treat Channel Pressure (what you call AT I think, monophonic AT) as a CC (CC#128) in Mapper X.
Talagan is offline   Reply With Quote
Old 12-07-2020, 03:45 PM   #209
Talagan
Human being with feelings
 
Join Date: Feb 2016
Location: Paris / France
Posts: 161
Default

@mschnell : after thought, and having had a look at the MIDI spec, there's something that seems totally unclear to me. At the time I implemented HR Midi, it was obvious for me that the HR midi spec for CCs was LSB first, (LSB event arriving first, then arrives a companion MSB event) for two reasons :

1) CC#88 High Res for velocity is LSB first in the spec (it's even called "prefix"). A CC#88 always precedes a note event.

2) High Res should be compatible with low res. With LSB first, you can easily trigger on the MSB event (the significant event) while having the full information received (you just have to buffer the LSB and you can aggregate the two of them when the MSB arrives). With MSB first you have to ... wait for the LSB to make a decision. Or you glitch. And it is possible that the LSB event may never arrive. So it introduces latency, even glitches in the system.

But this is what the spec states :

Quote:
If 128 steps of resolution is sufficient the second byte (LSB) of the data value can be omitted. If both the MSB and LSB are sent initially, a subsequent fine adjustment only requires the sending of the LSB. The MSB does not have to be retransmitted. If a subsequent major adjustment is necessary the MSB must be transmitted again. When an MSB is received, the receiver should set its concept of the LSB to zero.
So it's even worse, since for economy reasons, a part of the 14-bit value may be omitted.

I'm not the only one finding the spec unclear and even buggy, on that point, see that discussion :

https://community.vcvrack.com/t/14-b...in-1-0/1779/62

Now I see that ReaControlMIDI sends MSB first then LSB. So I'm curious to know what choices you made on that part if you did implement support for High Res MIDI in your plugins.

Edit: After having checked all cases on the paper, it looks like that MIDI specification simply does not work at all without glitches on the receiver side, or other drawbacks. I'd be interested to be proven wrong if someone has some experience on HR Midi and I can develop further. (I'm talking about CC#0-31. For velocity, since in HR there's always a CC#88 LSB prefix, it is robust).

Last edited by Talagan; 12-08-2020 at 01:41 PM.
Talagan is offline   Reply With Quote
Old 12-07-2020, 03:51 PM   #210
TonE
Human being with feelings
 
Join Date: Feb 2009
Location: Reaper HAS send control via midi !!!
Posts: 2,989
Default

Does high-res midi use 14-bits also for velocity? Would be cool and quite detailed if so.
TonE is offline   Reply With Quote
Old 12-07-2020, 04:23 PM   #211
Talagan
Human being with feelings
 
Join Date: Feb 2016
Location: Paris / France
Posts: 161
Default

Quote:
Originally Posted by TonE View Post
Does high-res midi use 14-bits also for velocity? Would be cool and quite detailed if so.
Yes but it's a bit less than 14-bits, a few values are rejected IIRC : for MSB 0 any LSB value is forbidden (because MSB 0 is a note off, period). So you get something like (127 * 128 + 1) possible values instead of (128 * 128) values for 14-bit.

Last edited by Talagan; 12-07-2020 at 04:30 PM.
Talagan is offline   Reply With Quote
Old 12-08-2020, 11:50 PM   #212
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 10,042
Default

Quote:
Originally Posted by Talagan View Post
(LSB event arriving first, then arrives a companion MSB event)
Not really. The LSB and MSB events can be transferred independently. For small changes usually only LSB is transferred. Non HR senders don't send LSB, but HR receivers should work decently on that by ignoring LSB . Hence the receiver is required to store both and create a new value whenever either comes in. The sender should send only one if the other does not change.

I am not sure about the details with velocity, Here I do suppse that the LSB is transferred first, as the MSB comes as a trigger.

-Michael
mschnell is online now   Reply With Quote
Old 12-09-2020, 02:03 AM   #213
Talagan
Human being with feelings
 
Join Date: Feb 2016
Location: Paris / France
Posts: 161
Default

Quote:
Originally Posted by mschnell View Post
Not really. The LSB and MSB events can be transferred independently. For small changes usually only LSB is transferred. Non HR senders don't send LSB, but HR receivers should work decently on that by ignoring LSB . Hence the receiver is required to store both and create a new value whenever either comes in. The sender should send only one if the other does not change.
Ok, thanks for your answer, Michael. That's what I thought. In fact this does not work (sorry to put it so bluntly ).

Suppose the following sequence of values to be transmitted (MSB,LSB) :

Code:
65,1
65,123
66,2
66,87
This will result in the following events :

Code:
MSB 65
LSB 1
LSB 123
MSB 66
LSB 2
LSB 87
The problem is that on the receiver side, with the MSB+LSB event trigger approach, you always create values for each received event, so you create values that do not exist (here you reconstruct 6 values instead of 4).

In some sequences this would probably work quite well, but here it's a problem see :

Code:
MSB 65  -> 65,0
LSB 1   -> 65,1
LSB 123 -> 65,123
MSB 66  -> 66,123  --> MEGA GLITCH
LSB 2   -> 66,2
LSB 87  -> 66,87
In a monotonous ascending sequence you will create sawtooth steps when the LSB is high.

That's the reason why, I think, they say to clear the LSB to zero on MSB events : to be sure there's no trailing LSB and keep the monotony.

BUT.

It does not work for a monotonous descending sequence. If you create an example of a sequence with descending values like the precedent one, you'll see that the 0-cleared MSB events will create sawtooth steps too.

If you try (as I did) to search on a paper if there's an implementation that works among all those possibilities (LSB first, MSB first, trigger or not on LSB, trigger or not on MSB), you'll see that all have problems. The only one which is almost ok is MSB first, trigger on LSB only. But this means that if the emitter is low res, you trigger on nothing and it does not work, so you're not low res compatible.

For all of those reasons, I don't see how it's possible to implement this correctly without forward event lookup and timeouts (and even then it might be glitchy for some other reasons).

Last edited by Talagan; 12-09-2020 at 02:13 AM.
Talagan is offline   Reply With Quote
Old 12-09-2020, 05:05 PM   #214
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 10,042
Default

Quote:
Originally Posted by Talagan View Post
For all of those reasons, I don't see how it's possible to implement this correctly without forward event lookup and timeouts (and even then it might be glitchy for some other reasons).
I do see that you are correct.

Of course if both values change (e.g. 23,127 -> 24,0), the sender will issue both messages. independent of which is sent first a glitch will appear.

I also don't see a way to avoid this other than by implementing some kind of delay waiting if the other message might be detected. Not nice at all !
Of course with use of USB this delay can be very short. but also rather undefined.

In fact Reaper uses an implementation of a HR Midi receiver for parameter modulation in [Param] -> Parameter Modulation Midi link.
No idea how they do that.

Let me know if you find out more...
-Michael

Last edited by mschnell; 12-10-2020 at 05:49 AM.
mschnell is online now   Reply With Quote
Old 12-10-2020, 02:19 AM   #215
Talagan
Human being with feelings
 
Join Date: Feb 2016
Location: Paris / France
Posts: 161
Default

Yes, no problem. Thanks for confirming

I'm a bit a bit flooded by work atm, so I'll continue thinking about it for a few days before starting an implementation.

So far, my preferred solution is :

1) Propose HR on a control input or output only if a LSB cc is selected (instead of MSB in the current version).

2) Don't emit events on MSB, just store the MSB for subsequent LSB values.

3) On LSB, reconstruct the value, and ALWAYS send MSB+LSB for the new value.

That way, the UI will be more coherent, in that sense that it makes it clear that HR in Mapper X is LSB-driven. The implementation should not jitter (except on initial values if the very first MSB is missing, which is acceptable, say). This will also normalize the flow to always prefix with the MSB but that will use more bandwidth on the output. But we're in 2020 so I don't think it's shocking especially when we see how that MSB-economy thing is a problem. That issue will simply disappear with MIDI 2.0 in a (near ?) (future ?)

Also, I really don't feel like implementing forward lookup and timeout mechanisms ; in JSFX it's not that easy to have queues and delays and the source for MIDI Mapper X is already big so I admit I'd like to avoid an implementation nightmare .

So it's probably no surprise that HR MIDI is quite obscure and confidential. I would have expected more from the spec than "oh yeah maybe you'll have some jitter so put the MSB at 0 (and pray... oh wait, it won't probably work... pray more)", especially when you're trying to propose fine-grained resolution and the jitter is potentially of the size of your MSB! The receiver design is left to the person implementing it, but I find that part should have been more documented.

PS : One possible option I see for forward lookup is when you receive a MSB, get the next MIDI event. If it's not the companion LSB, handle the MSB event as stand-alone (and then handle the next event). If it's the companion LSB, handle the pair (and eat the LSB event). If there's no next event in the @block, handle as stand-alone (@block is thus used as a kind of timeout). Even then, I make suppositions and I'm not sure it's clean. It also implies that you need to implement a rolling system currentEvent/nextEvent when you midirecv to offer forward lookup without crazy push/pop mechanisms.

Last edited by Talagan; 12-10-2020 at 02:06 PM.
Talagan is offline   Reply With Quote
Old 12-10-2020, 05:27 AM   #216
Talagan
Human being with feelings
 
Join Date: Feb 2016
Location: Paris / France
Posts: 161
Default

FI, the guys from Haken (Continuum Fingerboard) speak about that problem too on their website and how they use their own protocol extension to solve the problem.
Talagan is offline   Reply With Quote
Old 12-10-2020, 06:03 AM   #217
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 10,042
Default

We are in a kind of catch 22, here.

When doing a HR CC Midi sender, you just only send the 7 bits that changed, to allow for optimum efficiency of the data stream.

When doing a device that uses HR CC for a dedicated purpose (Filter, Volume, ...) you do know how fast your device reacts on changes and you easily can implement an appropriate hold-off to be save with the glitches.

This obviously is how HR Midi CC is supposed to work.

But if we are an intermediate "Mapper", we are f***ed, as we don't know how to set the delay.

I suggest that the only decent way is to provide a slider that allows for setting the delay according to the application in question. The default value should be according to the plain old 5-pin Midi definition: 3 Bytes, with 10 bits each -> 30 Bit @ 50 KBaud -> 0.6 mSec -> say 1 mSec.

-Michael

Last edited by mschnell; 12-18-2020 at 11:54 PM.
mschnell is online now   Reply With Quote
Old 12-18-2020, 01:41 PM   #218
Talagan
Human being with feelings
 
Join Date: Feb 2016
Location: Paris / France
Posts: 161
Default

Hi Michael, I do agree with you in the fact that it's complicated to implement a non-intrusive mapper here and that we have to make choices. I have an additional remark : it looks like ReaControlMidi always emits the MSB event even if the MSB does not change (when you select a HR control in ReaControlMidi and move the slider with the mouse it can be easily observed with a MIDI logger put right after in the stack). It does comfort me in doing the same for the calculated output of Mapper X and avoid making the economy of the MSB.
Talagan is offline   Reply With Quote
Old 12-19-2020, 12:00 AM   #219
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 10,042
Default

As you don't know the sender of the messages, not using a holdoff delay seems to be viable as an option, but not as the only one.
OTOH, if you do a completely direct translation based on the stored part of the value (this is how my implementations work nowadays), there is much hope that the receiver will implement a holdoff for the reasons we discussed, and by this any glitch produced by the mapping should be filtered out, anyway. Hence this is a viable option as well.

-Michael

Last edited by mschnell; 12-19-2020 at 12:44 AM.
mschnell is online now   Reply With Quote
Old 12-26-2020, 10:01 AM   #220
cjunekim
Human being with feelings
 
Join Date: Dec 2016
Posts: 193
Default 14-bit midi cc wrong implementation?

The high resolution midi message implementation might be wrong in Midi CC mapper X.

The order is in LSB and then MSB, but it should be MSB and then LSB, I think.

Please have a look into a github issue page that I created : https://github.com/helgoboss/realearn/issues/76
cjunekim is offline   Reply With Quote
Old 12-26-2020, 10:06 AM   #221
Talagan
Human being with feelings
 
Join Date: Feb 2016
Location: Paris / France
Posts: 161
Default

Quote:
Originally Posted by cjunekim View Post
The high resolution midi message implementation might be wrong in Midi CC mapper X.

The order is in LSB and then MSB, but it should be MSB and then LSB, I think.

Please have a look into a github issue page that I created : https://github.com/helgoboss/realearn/issues/76
Thanks @cjunekim for reporting! This problem is the subject of our recent discussion with @mschnell and it's already in the pipe but needs a bit of rework to make things clear in the plugin. Should be on rails in a few days If you're interested in why it's not that trivial and easy to handle 14-bit MIDI messages, you can have a read of the preceding 10 messages or so.

Last edited by Talagan; 12-26-2020 at 10:18 AM.
Talagan is offline   Reply With Quote
Old 12-27-2020, 08:07 AM   #222
Talagan
Human being with feelings
 
Join Date: Feb 2016
Location: Paris / France
Posts: 161
Default

Adding notes for the next development. From what I've observed :

- ReaControlMIDI always outputs MSB+LSB for 14-bit controls. So it does not try to make the economy of the MSB when emitting. REAPER's choice here is greedy (and I think that's for the best).
- When drawing in a 14-bit CC lane, REAPER always adds a MSB and a LSB event. So same remark as precedent.
- When sending unconnected LSB and MSB events for a same 14-bit control, REAPER does not show LSB events in the 14-bit CC Lane. It only shows MSB events. So in the way it displays the 14-bit CC Lane, REAPER considers that a 14-bit CC event is made of a necessary MSB event and an optional LSB event. If both MSB and LSB are present at the same time, the aggregated value in the 14-bit CC lane is the sum of the MSB + LSB.
- If a LSB event precedes an MSB event but is not synchronized with it, the value in the 14-bit CC Lane does only take the MSB event into account and does not aggregate the preceding LSB.
- Selecting an event in the 14-bit CC Lane will select corresponding events in the MSB AND LSB lanes if they are synchronized. Of course, the reverse is not true. So it's easy to screw up the synchronization between the MSB and LSB lanes and end up with unsynchronized events when editing things separately.

Pheeeewwww. It's gonna be hard to make a clean, easy to understand implementation.

Last edited by Talagan; 12-27-2020 at 08:16 AM.
Talagan is offline   Reply With Quote
Old 12-28-2020, 06:40 AM   #223
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 10,042
Default

When analyzing the woring of Midi events in reaper itself it should be considered, how Midi events are "timed" within Reaper - but not when send out to or received by hardware and not necessarily when handled by any plugins.

All Midi events are associated with sample blocks and denoted by an offset in samples. So effectively they are associated with a single sample. If multiple midi events are associated with the same sample their precedence is random, (In fact I did see that their sequence can be swapped).

Hence a discussion if first sending or receiving MSB or LSB is futile for Midi events that are sent by a JSFX (in the same @block call and with the same offset). You need to be aware of any order, but you don't need any special handling if both are received in that way.

OTOH, you can't be sure that some previous plugin or hardware creates the events as "singles" for more efficiency. Or if there is a delay of any kind that produces a pair with different offset or even in different blocks.

BTW you might consider to create a sequence order by incrementing the offset, but here I don't know what will happen in the (rare) case that the offset is greater that the sample block size.

-Michael
mschnell is online now   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 01:24 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, vBulletin Solutions Inc.