[Help] add_midi_mapping for control a slider

I have a question about adding MIDI input for a slider:

For example, I have defined my sliders as well:

Case A , slider for panning (with max = 127):

vb:slider {
  id = "PAN_SLIDER",
  width = 22,
  height = 652,
  min = 0,
  max = 127,
  value = 64,
  notifier = function() vpd_pan_value() end
}

Case B , slider for delay (with max = 255):

vb:slider {
  id = "DLY_SLIDER",
  width = 22,
  height = 652,
  min = 0,
  max = 255,
  notifier = function() vpd_dly_value() end
}

It is possible to assign a midi input with renoise.tool():add_midi_mapping() to control this kind of sliders?Is it possible to do it accurately?Is there a problem with the maximum value?The three ranges I use are: 0 to 120 (notes), 0 to 127 (volume, panning) and 0 to 255 (delay, effects).

The objective is to be able to control them from a fader (or even a wheel) of a USB MIDI Keyboard or of a USB MIDI Pad.

I have already built buttons and linking to add_midi_mapping, but I do not know how to do it for a slider.

Please, help!

Thanks!

Doc. info:

Click to view contents

–[[

midi_mappings: Extend Renoise’s default MIDI mapping set, or add custom MIDI

mappings for your tools.

The Lua table passed to ‘add_midi_mapping’ is defined as:

  • Required fields:
  • [“name”] = The group, name of the midi mapping; as visible to the user.

  • [“invoke”] = A function that is called to handle a bound MIDI message.

The mappings ‘name’ should have more than 1 part, separated by “:” e.g.

[topic_name:optional_sub_topic_name:name]

topic_name and optional sub group names will create new groups in the list

of MIDI mappings, as seen in Renoise’s MIDI mapping dialog.

If you can’t come up with a meaningful string, use your tool’s name as the topic

name. Existing global mappings from Renoise can be overridden. In this case the

original mappings are no longer called, only your tool’s mapping.

The “invoke” function gets called with one argument, the midi message, which

is modeled as:

class “renoise.ScriptingTool.MidiMessage”

– returns if action should be invoked

function is_trigger() -> boolean

– check which properties are valid

function: is_switch() -> boolean

function: is_rel_value() -> boolean

function: is_abs_value() -> boolean

– [0 - 127] for abs values, [-63 - 63] for relative values

– valid when is_rel_value() or is_abs_value() returns true, else undefined

property: int_value

– valid [true OR false] when :is_switch() returns true, else undefined

property: boolean_value

A tool’s MIDI mappings can be used just like the regular mappings in Renoise.

Either by manually looking up the mapping in the MIDI mapping

list, then binding it to a MIDI message, or when your tool has a custom GUI,

specifying the mapping via a control’s “control.midi_mapping” property. Such

controls will get highlighted as soon as the MIDI mapping dialog is opened.

Then, users simply click on the highlighted control to map MIDI messages.

]]

– Returns true when the given mapping already exists, otherwise false.

renoise.tool():has_midi_mapping(midi_mapping_name)

-> [boolean]

– Add a new midi_mapping entry as described above.

renoise.tool():add_midi_mapping(midi_mapping_definition_table)

– Remove a previously added midi mapping by specifying its name.

renoise.tool():remove_midi_mapping(midi_mapping_name)

The MIDI message you receive is limited to MIDI resolution, obviously.

So if you have a range of 0-255, and receiving absolute MIDI messages, some values can’t be reached.

The only solution here is on the controller part - if you configure your MIDI controller to send relative messages (this is / should automatically be detected by Renoise when you map the slider)

The MIDI message you receive is limited to MIDI resolution, obviously.

So if you have a range of 0-255, and receiving absolute MIDI messages, some values can’t be reached.

The only solution here is on the controller part - if you configure your MIDI controller to send relative messages (this is / should automatically be detected by Renoise when you map the slider)

Hi Danoise, Thanks!

Do you have any simple tool suggestions that have midi input for a slider?

A simple example to see how it is built.If it’s too complicated to build, I’d rather not implement it.For a range lower than 128 I think there is no problem, but for a range of up to 255 values it is something else.

Neither would anything happen if the precision was not accurate, but just half. A sliding value on the MIDI keyboard physical slider would equal 2 tool values. Or something like that…

I would point to the GlobalMidiActions file that comes with every Renoise installation:

https://github.com/renoise/xrnx/blob/master/GlobalMidiActions.lua

It provides a bit of background information and demonstrates all the available/supported methods and modes [set vs. toggle, absolute and relative values],

Take a good look at it, and come back here?

I would point to the GlobalMidiActions file that comes with every Renoise installation:

https://github.com/renoise/xrnx/blob/master/GlobalMidiActions.lua

Thank you for reminding me of such a file!!!I have been so immersed in other matters that I have completely ignored the existence of such a file. I feel a bit stupid now lol :wacko:.For some reason I tend to look only at the files inside the “Documentation” folder.I would have expected the files " GlobalMidiActions.lua" and " GlobalOSCActions.lua"to be inside the “Documentation” folder.I suppose there is some reason.Maybe they were included later?

A related question. Do these Github files constantly check you?I mean, if there is any change, or update, will it be reflected in that account? I see that there are files that seem to have been modified a few weeks ago.I do not usually use Github, but maybe I should get used to it.Possibly I’m looking at outdated files in my folder :huh:.

I think I can build it with GlobalMidiActions.lua. If I have any doubts, I will consult her here…

Thanks!

I think I can build it with GlobalMidiActions.lua

OK. I didn’t necessarily mean that you should add mappings through this file, but sometimes it’s easier than building a tool.

Just beware then of the following warning:

DO NOT EDIT THIS FILE IN THE RENOISE RESOURCE FOLDER! UPDATING RENOISE WILL
 TRASH YOUR MODIFICATIONS!
 
 TO EXTEND MIDI MAPPINGS, COPY THIS FILE TO THE RENOISE PREFERENCES SCRIPT 
 FOLDER, THEN DO YOUR CHANGES AND ADDITIONS THERE.

Just beware then of the following warning:

Yes, I have it in mind… Thanks!

I believe that I have never modified these files for my personal use. Maybe some strange bug I’ve detected, like missing add renoise.song() somewhere or something…

I mean, if there is any change, or update, will it be reflected in that account? I see that there are files that seem to have been modified a few weeks ago.I do not usually use Github, but maybe I should get used to it.Possibly I’m looking at outdated files in my folder :huh:.

The documentation is for the current version (API5), but might have received an update or two to reflect inaccuracies.
Some goes for the our tools (Renoise Team), updates are usually pushed on github before being released on the tools page.

If you haven’t used git before, I can highly recommend it. It lets you make mistakes and “roll them back”, effortlessly.
Git itself is a versioning protocol, which github has then built a large&successful business around.
So you don’t have to use github if you don’t feel like it - just pick a GUI that you feel comfortable with.
E.g. here’s a good selection if you are running Windows:
https://www.slant.co/topics/2089/viewpoints/7/~git-clients-for-windows~gitextensions

The documentation is for the current version (API5), but might have received an update or two to reflect inaccuracies.
Some goes for the our tools (Renoise Team), updates are usually pushed on github before being released on the tools page.

If you haven’t used git before, I can highly recommend it. It lets you make mistakes and “roll them back”, effortlessly.
Git itself is a versioning protocol, which github has then built a large&successful business around.
So you don’t have to use github if you don’t feel like it - just pick a GUI that you feel comfortable with.
E.g. here’s a good selection if you are running Windows:
https://www.slant.co/topics/2089/viewpoints/7/~git-clients-for-windows~gitextensions

Thanks for the Info! :slight_smile:

@Danoise.Thanks for the help!

Ok.I have been able to solve the MIDI input for most of my sliders. I think I have everything I need to complete my tool. But I would like to know if it is possible that with the absolute value it is possible to have an exact resolution for a range of 0 to 255. I know the range of the input value is 0 to 127. I have used a multiplier of 2.01 so that it reaches All range from 0 to 255 , but obviously not accurate. Not able to return half of the values. Is there any way to be exactly accurate with this range?

This is my “midi_input.lua”:

-----------------------------------------------------------------------------------
---CLASS "MIDI_IN"
-----------------------------------------------------------------------------------
class = "MIDI_IN"

MIDI_IN = {
  --slider
  NOT_SLIDER = "Tools:VPD:1. Slider:1. Note:Insert/Change Note Value [Set]",
  VOL_SLIDER = "Tools:VPD:1. Slider:2. Volume:Insert/Change Volume Value [Set]",
  PAN_SLIDER = "Tools:VPD:1. Slider:3. Panning:Insert/Change Panning Value [Set]",
  DLY_SLIDER = "Tools:VPD:1. Slider:4. Delay:Insert/Change Delay Value [Set]",
  EFF_SLIDER = "Tools:VPD:1. Slider:5. Effect:Insert/Change Effect Amount [Set]",
  
  --popup
  GUI_SFX_POPUP = "Tools:VPD:2. Popup:5.1 Sample Effect:Insert/Change Sample Effect Value (SFX) [Set]",
  GUI_TFX_POPUP = "Tools:VPD:2. Popup:5.2 Track Effect:Insert/Change Track Effect Value (TFX) [Set]",
  --button
  
}

-----------------------------------------------------------------------------------
---FUNCTIONS MIDI INPUT FOR SLIDER
-----------------------------------------------------------------------------------
--clamp_value
function clamp_value( value, min_value, max_value )
  return math.min( max_value, math.max(value, min_value) )
end

--message_value_with_offset
function message_value_with_offset_1( message, value, offset, min_value, max_value )
      if ( message:is_abs_value() ) then return clamp_value( message.int_value + offset, min_value, max_value )
  elseif ( message:is_rel_value() ) then return clamp_value( value + message.int_value, min_value, max_value )
  else
    return value
  end
end

function message_value_with_offset_2( message, value, offset, min_value, max_value )
      if ( message:is_abs_value() ) then return clamp_value( (message.int_value + offset )*2.01, min_value, max_value ) --> Is greater accuracy possible ??????
  elseif ( message:is_rel_value() ) then return clamp_value( value + message.int_value, min_value, max_value )
  else
    return value
  end
end

function message_value_with_offset_3( message, value, offset, min_value, max_value )
      if ( message:is_abs_value() ) then return clamp_value( (message.int_value + offset )/6, min_value, max_value )
  elseif ( message:is_rel_value() ) then return clamp_value( value + message.int_value, min_value, max_value )
  else
    return value
  end
end

function message_value_with_offset_4( message, value, offset, min_value, max_value )
      if ( message:is_abs_value() ) then return clamp_value( (message.int_value + offset )/3, min_value, max_value )
  elseif ( message:is_rel_value() ) then return clamp_value( value + message.int_value, min_value, max_value )
  else
    return value
  end
end

--message_value
function message_value_1( message, value, min_value, max_value )
  return message_value_with_offset_1( message, value, 0, min_value, max_value )
end

function message_value_2( message, value, min_value, max_value )
  return message_value_with_offset_2( message, value, 0, min_value, max_value )
end

function message_value_3( message, value, min_value, max_value )
  return message_value_with_offset_3( message, value, 0, min_value, max_value )
end

function message_value_4( message, value, min_value, max_value )
  return message_value_with_offset_4( message, value, 0, min_value, max_value )
end

-----------------------------------------------------------------------------------
---ADD MIDI MAPPING
-----------------------------------------------------------------------------------
--slider controller
renoise.tool():add_midi_mapping {
  name = MIDI_IN.NOT_SLIDER,
  invoke = function(message) if message:is_abs_value() then vb.views["NOT_SLIDER"].value = message_value_1( message, vb.views["NOT_SLIDER"].value, 0, 120 ) end end --OK (Absolute 7 bit) Precise!
}

renoise.tool():add_midi_mapping {
  name = MIDI_IN.VOL_SLIDER,
  invoke = function(message) if message:is_abs_value() then vb.views["VOL_SLIDER"].value = message_value_1( message, vb.views["VOL_SLIDER"].value, 0, 127 ) end end --OK (Absolute 7 bit) Precise!
}

renoise.tool():add_midi_mapping {
  name = MIDI_IN.PAN_SLIDER,
  invoke = function(message) if message:is_abs_value() then vb.views["PAN_SLIDER"].value = message_value_1( message, vb.views["PAN_SLIDER"].value, 0, 127 ) end end --OK (Absolute 7 bit) Precise!
}

renoise.tool():add_midi_mapping {
  name = MIDI_IN.DLY_SLIDER,
  invoke = function(message) if message:is_abs_value() then vb.views["DLY_SLIDER"].value = message_value_2( message, vb.views["DLY_SLIDER"].value, 0, 255 ) end end --OK (Absolute 7 bit) Only half of values!!!
}

renoise.tool():add_midi_mapping {
  name = MIDI_IN.EFF_SLIDER,
  invoke = function(message) if message:is_abs_value() then vb.views["EFF_SLIDER"].value = message_value_2( message, vb.views["EFF_SLIDER"].value, 0, 255 ) end end --OK (Absolute 7 bit) Only half of values!!!
}

--popup controller
renoise.tool():add_midi_mapping {
  name = MIDI_IN.GUI_SFX_POPUP,
  invoke = function(message) if message:is_abs_value() then vb.views["GUI_SFX_POPUP"].value = message_value_3( message, vb.views["GUI_SFX_POPUP"].value, 1, 19 ) end end --OK (Absolute 7 bit) Precise!
}

renoise.tool():add_midi_mapping {
  name = MIDI_IN.GUI_TFX_POPUP,
  invoke = function(message) if message:is_abs_value() then vb.views["GUI_TFX_POPUP"].value = message_value_4( message, vb.views["GUI_TFX_POPUP"].value, 1, 30 ) end end --OK (Absolute 7 bit) Precise!
}

--button controller

Am I doing the right steps with the code?I think it’s everything.Can you check it?It’s the first time I built it with sliders…

I’m going to control 5 sliders and 2 popup ( and many buttons) with MIDI input.I have checked that this setting works with my MIDI keyboard (Novation Lanchkey 61). With popup I not have problems…

The only problem is the precision of sliders with ID: “DLY_SLIDER” (for delay values) and “EFF_SLIDER” (for amount values of effects), that both use the same range: 0 to 255.

renoise.tool():add_midi_mapping {
  name = MIDI_IN.DLY_SLIDER,
  invoke = function(message) if message:is_abs_value() then vb.views["DLY_SLIDER"].value = message_value_2( message, vb.views["DLY_SLIDER"].value, 0, 255 ) end end --OK (Absolute 7 bit) Only half of values!!!
}

renoise.tool():add_midi_mapping {
  name = MIDI_IN.EFF_SLIDER,
  invoke = function(message) if message:is_abs_value() then vb.views["EFF_SLIDER"].value = message_value_2( message, vb.views["EFF_SLIDER"].value, 0, 255 ) end end --OK (Absolute 7 bit) Only half of values!!!
}

I am very happy with the results. Too bad these two sliders do not have the exact accuracy. Is there any way to fix it?The slider that worries me the most is theEFF_SLIDER, because there are some effects that need an exact amount…