Sign in to follow this  
Followers 0
ultra

encoder speed settings/acceleration

13 posts in this topic

i've been playing around with mios programming in c for the past few days.  i'm using endless rotary encoders and i've figured out how to get a knob to turn properly in ableton live using absolute midi values.

what i want to do now is use a relative mode in ableton live.  i've figured out how to use signed bit (sending 65 or 1), but it seems to take a lot more turning of the knob than when sending 0-127 values.  this seems weird to me because they should increment in the same amount.  for absolute values, i increment a counter by 1 on each encoder move event.  for relative values, i send the 65 value at the same frequency.  it takes a lot longer to turn the knob in relative mode.

i see that there are speed settings available, but i don't want to lose resolution.  i don't understand why using a counter would be any different than sending the command to increment repeatedly.

any ideas?

Share this post


Link to post
Share on other sites

Maybe Live supports 16 or 14 bits for the virtual knob values, so absolute mode will be scaled from 0...16384 or 0...32768 to 0...127 to match midi, and the relative mode allows for finer control at the higher bit depth?

You could test this by sending it a hardcoded incrementer value of +63 and see how far the knob moves around the dial . Just stick it in your init function and turn it on :)

Edit: If it has the higher bit depth then you can just bitshift the controller value with a shift button or push button encoder to make it go fast as absolute mode (or fine if you prefer). It'll send the full throw of +/-63 every time you move one notch. Actually, that's another way you could test it ;)

Share this post


Link to post
Share on other sites

thanks stryd, this works perfectly.

and for anybody else researching this, here's some answers:

relative midi generally sends the value 65 repeatedly to decrement, and 1 to increment.

using midi learn in ableton live, live will autmatically recognize it as signed bit if you turn the encoder slowly.  after receiving 1 or 65 twice it understands it's signed bit.

however, this moves the knob too slowly.  changing the values to 3 and 67 works perfectly for me (might end up changing by 1 value), but live won't recognize it as signed bit anymore.  so when in midi learn mode, just manually select it from the drop-down list on the bottom of the screen.

thanks again stryd :)

Share this post


Link to post
Share on other sites

Now, how to increase/decrease the values as the encoder rotates faster/slower ?

I'm still looking for this answer. ::)

Share this post


Link to post
Share on other sites

Now, how to increase/decrease the values as the encoder rotates faster/slower ?

Well if you want to support acceleration in hardware (Does Live not support this itself?), you need to use a timer/counter to calculate how many encoder inc/decrements in a given period of time, and then use that number to control an inc/decrease in the amount of the change you send to the host.

Share this post


Link to post
Share on other sites

i don't think any program understands acceleration.  when i send signed bit out from my axiom, the value increases with the speed.  so the acceleration is built into the keyboard.

i'm not sure i see a purpose for acceleration now that i have this working properly.  a value of 3/67 seems to work perfectly, as it does a full turn in about 3/4 of a knob turn.  perhaps a button to temporarily increase the value would be more appropriate.

Share this post


Link to post
Share on other sites

i don't think any program understands acceleration.

They could if they wanted to. But that wouldn't help sell controllers :)

when i send signed bit out from my axiom, the value increases with the speed.  so the acceleration is built into the keyboard.

Oh, so the axiom has a mode where you tell it that the knob should send knob movements as increments rather than an absolute value? That's not normal - as I keep saying, there's no such thing as relative midi - I'm guessing that the axiom has implemented a proprietary workaround which is common (sending signed 7bit values of inc/decrements) because a modern DAW has (finally caught on and) implemented it.

i'm not sure i see a purpose for acceleration now that i have this working properly. 

Sometimes it is handy... But I find that fast/slow mode is more functional as it allows more control.

a value of 3/67 seems to work perfectly

67? you mean -3? :D Should be more intuitive to use a signed value and then typecast it before you call txbufferput.

Share this post


Link to post
Share on other sites

it is called "relative midi" in both the live and axiom manuals.  sure it's no different than sending the same absolute values repeatedly (unless acceleration is taken into account), but it's still a standard that almost all DAW's will recognize (i read reaktor understands it as well), and some controllers will send.  in fact, live accepts four modes (signed bit, signed bit 2, binary offset, and 2's complement) and i think the axiom can send six.

in signed bit mode, sending a CC with the value 65 tells live to increment 1 value.  sending a value of 1 tells it to decrement.  the incrementing values can be anywhere from 65-127, and the decrement values are 1-64.

when live is in midi learn mode, it looks at the values being received and not just the control change number and channel.  if it receives two commands in a row that both are at 65 or 1, it understands signed bit is being used and automatically puts itself into that mode.  then (again without acceleration being taken into account) my controller repeatedly sends 65 to increment or 1 to decrement.  when moving the encoder faster, the values of 65 and 1 increase to tell live to move the knob faster.  sending 65/1 is actually very slow, high resolution movement and it doesn't have a normal feel to it.  this is why i used 67/3 instead, to add 2 values (movement seems to increase exponentially with higher values) and make the movement seem more natural.  so the DAW is actually taking acceleration into account by responding differently to different values, but it makes sense that the controller would decide how much it is being accelerated.

one thing to note:  if you have live in midi learn mode and the controller does not send 65/1 (say you move an accelerating encoder fast), live will get confused and default to absolute mode.  so your "slow" mode should be used to send the correct 65/1 values.  otherwise while in midi learn mode, live does have a drop-down box to choose which mode you're using, so you can still get away with sending incorrect values.

Share this post


Link to post
Share on other sites

Did you already try this example?

-> http://www.ucapps.de/mios_c_send_enc_rel.html

It sends relative events (0x40 +/- <speed>) - if you need a different format, just change the ENC_NotifyChange() function.

If encoders are still too slow, incresse the divider setting in MIOS_ENC_SpeedSet(), e.g. use 4 instead of 2 (7 is maximum)

No other changes are required, especially no hacks with a timer function or similar - everything is already provided by MIOS

Best Regards, Thorsten.

Share this post


Link to post
Share on other sites

Yeh I know all that...Remember I was in the chat and helped you fix that bug?  ;D But read the midi spec and you won't find "relative midi". The only such thing is an RPN. The way your gear is working (sends a signed 7bit value) is a sensible implementation, and it is becoming the most widely used.... but similar - but not the same - methods have been used in the past, so it should not be spoken of as a universal implementation, because different devices and hosts do it different ways. Edit: like NI apparently, and I do the same as them in my seq ;)

in fact, live accepts four modes (signed bit, signed bit 2, binary offset, and 2's complement) and i think the axiom can send six.

Exactly. Ever wonder why that is?  ;D Because there's no such thing as relative midi CC's so everyone cooks it up a different way. You can bet your bottom dollar that it'll be included in the midi spec one day because it makes sense with modern gear ... But it's not yet :) Regardless, this is great info for people trying to get it working. I'll try and give up something useful:


unsigned char s_to_rel(signed char input) {							//input a signed char
	unsigned char sign; 											//holds the sign for later
	unsigned char output; 											//temp var for the output
	sign = 0;
	if (input&0x80) sign = 0x40; 									//set the 7th bit sign for later
	output = ((unsigned char) input)&0x7f;							//typecast then mask out the sign so we can work on the value
	if (output&0x40) output = output>>1;							//if it's using the full range, shift right for midi compatibility

	return (output|sign);											//put the sign back on there and return unsigned char representing signed 7bit
}


signed char rel_to_s(unsigned char input, unsigned char res) {	//input unigned char and range
	unsigned char sign; 											//holds the sign for later
	signed char output; 											//temp var for the output
	sign = 0;
	if (input&0x40) sign = 0x80; 									//set the sign for later
	output = ((signed char) input)&0x3f;								//typecast then mask out the sign so we can work on the value
	if (res) output = output<<1;									//if res is !0 then make this use full 7bit res+sign

	return (output|sign);											//put the sign back on there and return it
}

@tk hahahah we thought acceleration was built in but couldn't find any documentation and didn't have luck making it work, so thought it must have been part of the mb64 app... d'oh!

Share this post


Link to post
Share on other sites

So long an encoder is in normal mode, you won't notice any acceleration effect, because MIDI events are sent faster than the time between the "clicks"

Once you are using "fast speed" mode, the incrementer changes as specified here


MIOS_ENC_SPEED_FAST
  ~~~~~~~~~~~~~~~~~~~
  // in this speed mode the increment value depends on the
  // rotational speed based on the following formula:

  //    speed_ctr: decremented with every update cycle
  //    (-> MIOS_SRIO_UpdateFrqSet)
  //     (normaly 1 ms) to measure the time between
  //     two encoder steps
  //     Init value: 0x7f
  //     reaches 0x00 after 127 update cycles
  //    (normaly after 127 ms)
  //    <parameter>: specified with the MIOS_ENC_SpeedSet
  //
  //           function, allowed values:
  //        0 (fast)     -> divider = 2^(7-0) = 128
  //        1 (faster)   -> divider = 2^(7-1) =  64
  //        ...
  //        7 (fastest)  -> divider = 2^(7-7) =  1
  // ->
  //    incrementer = speed_ctr / (2^(7-parameter))

  // set speed for encoder #0 to "fast", speed exponent value is 2
  MIOS_ENC_SpeedSet(0, MIOS_ENC_SPEED_FAST, 2);
[/code]

So, I don't know why people are not searching in the MIOS function reference and in existing C examples? Sometimes, it really seems to me as it was wasted effort to write down all the details, because people will ask in the forum anyhow :/

Best Regards, Thorsten.

Share this post


Link to post
Share on other sites

Yes I think we both learned a lesson here....

First, bugfight and I helped ultra for some time, only to find that the encoder table was filled incorrectly. Solution? Use the examples.

Also, I didn't try it myself because I didn't have a DIN board soldered up. In the end, I spent more time typing, trying to help, than it would take to solder up the board. Solution? Just solder it and try it. It may take longer, but at least you get a soldered PCB a the end ;)

So, my apologies TK. Your effort wasn't a waste and we do appreciate it, and usually make use of it... just... sometimes we do daft things. Lesson learned!

Share this post


Link to post
Share on other sites

thanks guys.  i've only been programming using mios for the past week (it's my first c programming besides my class in school) so i haven't seen a lot of this kind of thing yet.  tomorrow night i will definitely be playing around with this and try to better understand what you guys have said. :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0