Allen & Heath K1 duplex mapping

Hey there -

I’m a bit stuck setting up two Allen & Heath K1 controllerto work with Duplex. Basically I would like to assign certain effect parameter mappings permanentlyto knobs and buttons of the K1s while at the same time avoid triggering notes by the synchronous running Traktor mapping. The two K1’s control Native Instruments Traktor, and the idea is to have access to plug in delay time parameters, feedback, etc. which are hosted inside Renoise.

The midi implementation is pretty straightforward, just really struggling with the .xml and Lua side of things.

Any help would be greatly appreciated!

The K1 sends Note On messages with a velocity of 127 out when pressed, and on release of a button, a Note off Message with a velocity of 0 is send out.

http://www.allen-heath.com/ahproducts/xonek1/

Start with the basics - here is an example I prepared:

Controlmap:

<Device>
  <Name>AllenHeithK1</Name>
  <Author>danoise</Author>
  <Description>Controlmap for AllenHeithK1</Description>
  <Parameters>
    <Page>
      <Row>
        <Column>
          <Group name="Buttons" orientation="horizontal">
            <Param value="C-4|Ch1" type="button" maximum="127" minimum="0"/>
            <Param value="C#4|Ch1" type="button" maximum="127" minimum="0"/>
            <Param value="D-4" type="button" maximum="127" minimum="0"/>
            <Param value="D#4" type="button" maximum="127" minimum="0"/>
          </Group>
        </Column>
      </Row>
    </Page>
  </Parameters>
</Device>

You will have to replace the notes with the actual ones that the K1 is transmitting.

If you don’t care about channels, strip them away (like I did with D-4 and D#4).

Next, the configuration file:

--[[----------------------------------------------------------------------------
-- Duplex.AllenHeathK1
----------------------------------------------------------------------------]]--

duplex_configurations:insert {

  -- configuration properties
  name = "BaseConfig",
  pinned = true,

  -- device properties
  device = {
    --class_name = nil, -- not used
    --thumbnail = "", -- not used
    display_name = "AllenHeathK1",
    device_port_in = "",
    device_port_out = "",
    control_map = "Controllers/AllenHeathK1/Controlmaps/AllenHeathK1.xml",
    protocol = DEVICE_PROTOCOL.MIDI
  },
  
  applications = {
    Transport = {
      mappings = {
        stop_playback = {
          group_name = "Buttons",
          index = 1,
        },
        start_playback = {
          group_name = "Buttons",
          index = 2,
        },

      }
    },

  }
}

This one is hooking up the Transport application - just two buttons: start and stop.

It’s good for testing, as pressing play will light that button and pressing stop will turn off the play button.

The files are in the attached zip file. Extract it into the Duplex/Controllers folder and fire up your text editor

(hint: you probably want to enable the scripting console - this can be used for editing the files within Renoise itself, and also, allows you to quickly reload the tool to test the changes).

Thanks Danoise! Got it to run, I will try to write up the proper knobs/ button layout in the next couple of days.

unfortunately still stuck!

I’m pretty sure that it’s related to placing the right files into the right directories, but I really don’t know how to do it.

These are the error messages I get:

failed to load controller definition file:

‘Controllers/AllenHeathK1/Controlmaps/AllenHeathK1.xml’. The controller is not available

Message from Duplex: the application Transport has been stopped - the control-map group ‘Buttons’. does not exist. Please review the device settings and/ or control-map (other applications will continue to run)

Script not responding

‘/User/UsernameHere/Library/Preferences/Renoise/V3.1.0/Scipts/Tools/com.renoise.Duplex.xrnx/main.lua’ may be busy or may have stopped responding.

You can stop the script now, in order to avoid freezing the whole program or continue waiting for it to complete.

Terminate Script?

‘/Users?UsernameHere/Library/Preferences/Renoise/V3.1.0/Scripts/Tools/com.renoiseDuplex.xrnx/main.lua’ failed in one of its notifiers.

OK, so the configuration has loaded but it can’t locate the control-map

Can you confirm that the following path exists?

[path to renoise tools]\com.renoise.Duplex.xrnx\Duplex\Controllers\AllenHeathK1

To find the tools path, head into Tools > Tool Browser, then right-click com.renoise.Duplex.xrnx and select ‘Reveal in Finder/Explorer’

Yes, the path exists. I prefixed it with a 0_ but changed it back toAllenHeathK1.

How do I set up now the mapping for the K1? I.e. write the script which defines the encoders, knobs and button?

Pardon if this is obvious, really trying to find my way around it…

So, you’re saying that you fixed the path and now it’s able to load the configuration without problems?

Then it is a matter of diving into the XML first - I just did a basic example with four buttons, not a complete representation of the A+H hardware.

Think of it as a starting point :slight_smile:

Satobox did a nice write up on how to edit the configuration and control-maps:

https://forum.renoise.com/t/how-to-start-editing-duplex-files/30979

Once you have a better representation of the hardware, check out the docs for details on how the configuration file is laid out

https://github.com/renoise/xrnx/blob/master/Tools/com.renoise.Duplex.xrnx/Docs/Configurations.md

How do I bring up the four buttons you mapped out?

If the configuration is at the right location and able to load (?), then it should available from the Duplex menu, just like any other configuration.

Tools > Duplex > AllenHeathK1

Don’t forget to set your input & output ports the first time you load it.

I got a basic setup to work. Thanks for you help!

The buttons do not work yet - I think they need to point to the right class (?) in the Effect.lua file?

How are the encoders ‘hardcoded’ to specific effect or device parameters? In other words, how to avoidwhen selecting another effect/ device in the mixer window, that then the knobs get automatically mapped to the selected device?

<Device>
  <Name>AllenHeithK1</Name>
  <Author>danoise</Author>
  <Description>Controlmap for AllenHeithK1</Description>
  <Parameters>
    <Row>
      <Column>

      </Column>
      <Column>
        <Row>
          <Group name="Encoder1" orientation="vertical" columns="1">
            <Param value="CC#4|Ch2" maximum="127" minimum="0" type="dial" size="1.5" />
            <Param value="C-4|Ch2" maximum="127" minimum="0" type="button" size="1.5" aspect="0.5" />
          </Group>

          <Group name="Encoder2" orientation="vertical" columns="1">
            <Param value="CC#5|Ch2" maximum="127" minimum="0" type="dial" size="1.5" />
            <Param value="C#4|Ch2" maximum="127" minimum="0" type="button" size="1.5" aspect="0.5" />
          </Group>

          <Group name="Encoder3" orientation="vertical" columns="1">
            <Param value="CC#6|Ch2" maximum="127" minimum="0" type="dial" size="1.5" />
            <Param value="D-4|Ch2" maximum="127" minimum="0" type="button" size="1.5" aspect="0.5" />
          </Group>

          <Group name="Encoder4" orientation="vertical" columns="1">
            <Param value="CC#7|Ch2" maximum="127" minimum="0" type="dial" size="1.5" />
            <Param value="D#4|Ch2" maximum="127" minimum="0" type="button" size="1.5" aspect="0.5" />
          </Group>
        </Row>

        <Row>
          <Group name="Encoder5" orientation="vertical" columns="1">
            <Param value="CC#8|Ch2" maximum="127" minimum="0" type="dial" size="1.5"/>
            <Param value="G#3|Ch2" maximum="127" minimum="0" type="button" size="1.5" aspect="0.5"/>
          </Group>
          <Group name="Encoder6" orientation="vertical" columns="1">
            <Param value="CC#9|Ch2" maximum="127" minimum="0" type="dial" size="1.5" />
            <Param value="A-3|Ch2" maximum="127" minimum="0" type="button" size="1.5" aspect="0.5"/>
          </Group>
          <Group name="Encoder7" orientation="vertical" columns="1">
            <Param value="CC#10|Ch2" maximum="127" minimum="0" type="dial" size="1.5" />
            <Param value="A#3|Ch2" maximum="127" minimum="0" type="button" size="1.5" aspect="0.5"/>
          </Group>
          <Group name="Encoder8" orientation="vertical" columns="1">
            <Param value="CC#11|Ch2" maximum="127" minimum="0" type="dial" size="1.5" />
            <Param value="B-3|Ch2" maximum="127" minimum="0" type="button" size="1.5" aspect="0.5"/>
          </Group>
        </Row>

        <Row>
          <Group name="Encoder9" orientation="vertical" columns="1">
            <Param value="CC#12|Ch2" maximum="127" minimum="0" type="dial" size="1.5" />
            <Param value="E-3|Ch2" maximum="127" minimum="0" type="button" size="1.5" aspect="0.5"/>
          </Group>
          <Group name="Encoder10" orientation="vertical" columns="1">
            <Param value="CC#13|Ch2" maximum="127" minimum="0" type="dial" size="1.5" />
            <Param value="F-3|Ch2" maximum="127" minimum="0" type="button" size="1.5" aspect="0.5"/>
          </Group>
          <Group name="Encoder11" orientation="vertical" columns="1">
            <Param value="CC#14|Ch2" maximum="127" minimum="0" type="dial" size="1.5" />
            <Param value="F#3|Ch2" maximum="127" minimum="0" type="button" size="1.5" aspect="0.5"/>
          </Group>
          <Group name="Encoder12" orientation="vertical" columns="1">
            <Param value="CC#15|Ch2" maximum="127" minimum="0" type="dial" size="1.5" />
            <Param value="G-3|Ch2" maximum="127" minimum="0" type="button" size="1.5" aspect="0.5"/>
          </Group>
        </Row>

        
      </Column>
      <Column>
        
      </Column>
    </Row>

  </Parameters>
</Device>
--[[----------------------------------------------------------------------------
-- Duplex.AllenHeathK1
----------------------------------------------------------------------------]]--

duplex_configurations:insert {

  -- configuration properties
  name = "Effects",
  pinned = true,

  -- device properties
  device = {
    --class_name = nil,
    display_name = "AllenHeathK1",
    device_port_in = "",
    device_port_out = "",
    control_map = "Controllers/AllenHeathK1/Controlmaps/AllenHeathK1.xml",
    --thumbnail = "",
    protocol = DEVICE_PROTOCOL.MIDI
  },
  
  applications = {
    Effect = {
      mappings = {
        parameters = {
          group_name = "Encoder*",
          index = 1,
          
        },

      },
    },

  }
}

how to avoidwhen selecting another effect/ device in the mixer window, that then the knobs get automatically mapped to the selected device?

Sorry, but the Effect application is based on automapping parameters. There is an option though that might be interesting - “parameter subsets” can include all_visible_parameters, as shown in the Renoise mixer view. Essentially, this will allow you to cherry-pick which parameters to showfor an entire track (you can right-click the device in the mixer to determine which parameters are visible)

I got a basic setup to work. Thanks for you help!

The buttons do not work yet - I think they need to point to the right class (?) in the Effect.lua file?

“Not working” - are they triggering something in Renoise, but not receiving visual feedback, or are they not working at all?

You might have to try with different button types - depends on what the controller sends.

These are the various types that you can specify in the control-map:

https://renoise.github.io/luadocs/duplex/modules/Duplex.Globals.html#INPUT_TYPE

Most likely, you have them set right already to ‘button’ - another thing to check is the minimum and maximum - this need to match with what the controller is transmitting - not always 0 and 127!

@danoise: “parameter subsets” - that seems to be the right ally to go down! Would the mapping remain locked to specific plugin parameters after adding another effect before the plugin in question?

I tried ‘pushbutton’, ‘togglebutton’ and 'button - still no visual feedback. The values correspond to what Renoise receives in the midi in monitor (I also tried different min/ max values, same result).

@danoise: “parameter subsets” - that seems to be the right ally to go down! Would the mapping remain locked to specific plugin parameters after adding another effect before the plugin in question?

Well, have you tried it? :)The parameters should appear in the same order as they do in the mixer - and change as you switch from track to track, always reflecting the parameters in the selected track.

But you can only change the order of parameters by changing the order of the actual devices. Your controller would be reflecting the Renoise “state” in realtime, basically.

Btw: since the Effect is following the active track, something like the Track Selector should be interesting as well:

https://github.com/renoise/xrnx/blob/master/Tools/com.renoise.Duplex.xrnx/Docs/Applications/TrackSelector.md

I especially like to have a shortcut for taking me to the master track. Very handy place to put e.g. a bunch of Hydras (controlling the overall automation/mix)

Regarding the lack of feedback: I’m sure it’s just a tiny detail that is missing. I read a bit about the MIDI specs of the A+H unit, but can’t really remember if there was something specific to be aware of…

Well, have you tried it? :slight_smile:

Not yet. Every baby step in Lua takes me ages. Slow and steady I guess…

No coding required :smiley:

Applications can be configured in the Duplex options too - this changes the behavior in realtime, so you can experiment and find a good setting.

Once you are happy with it, you could always specify the exact same options for the actual configuration - so it will start with those settings on a fresh install.