Always consult the Owners Manuals first


From Axe-Fx II Wiki
Jump to: navigation, search

AxeForLemur is a Lemur Template designed by David Sorlien to control the Axe-Fx. The Template runs on the Lemur APP by Liine, and connects wirelessly through a logical midi connection to the AxeFx.
This page is intended for users and developers of this template.


AxeForLemur is a JZML script, licensed by Creative Commons to be a non-commercial, free to use script. The script runs on IOS and Android devices with the Lemur Application from Liine. The Lemur Application communicates with the Axe-Fx either through direct MIDI connection, or through Wifi to a Host Computer, that is connected either through USB or MIDI to the Axe-Fx.

To configure an IOS/Android Patch Editor for the AxeFx:

  1. Purchase the Lemur App ( $20-$35 ) and install it on your Tablet or iPAD.
  2. Go to the Liine Website and register yourself as a user, then download, the Lemur Editor and Daemon Software.
  3. Connect your Tablet to your computer's IP network. Verify IP address, and ping your tablet to verify.
  4. Start the Lemur App on your Tablet or IPad.
  5. Download an AxeForLemur.jzml script. Current version is 3.08.
  6. On your PC run the LemurEditor and load the AxeForLemur.jzml script, Click Connect to send the script to your Tablet or IPAD.
  7. You should see the AxeForLemur Script on your IPAD, on the Default AMP page.
  8. If your AxeFx is connected to your PC/MAC through a USB cable, run the LIINE LEMUR DAEMON on your machine. This DEAMON will provide an IP Socket on the Network for MIDI and OSC communications from the IPAD to any MIDI devices on your PC/MAC.
  9. Within Lemur on your Tablet Open the Settings drop down list and select "More Settings...", Setup Midi Targets, From: and To:. You may need tap Add Target. You should see a list of network computers, with MIDI devices high lit. Choose AxeFx from the computer that is running the LEMUR DAEMON, for both "From: and "To:. If no devices show up, please verify the IPAD is connected to the IP network, and that the Lemur Daemon is running, and the AxeFX is turned on, and it is connected with USB or MIDI cable.
  10. On the Preset Select page of the AxeForLemur script, configure the midi settings to match your setup. Example, Column-A should Device should be set to AxeFxII or AxeFxXL+ etc, midi channel to '1' to match your MIDI settings, and Lemur target set to the Target within the Lemur Menu.
  11. Test by Tapping the Preset Up/Down.
  12. Troubleshooting can be a bit challenging and might require a bit of system debug and tweaking.


Design background into key elements of the AxeToLemur script:

Axe For Lemur is a comprehensive Lemur script based in Quasi XML, Objector based C-Script with out pre-processor, structures, pointers etc. The Script is object based, and exists in the JazzInterface tab object AxeForLemur. Global references exist in this scope.

Design Initialization

Design Device Selection

The preset page (AxeForLemur/dlgProgChange/T1) Contains a Matrix of Midi settings for up to 4 target devices.

For each 'Target Device' The user can select and increment/decrement (cTargets/padUpDn) the following (cTargets/swSettings):

  • Type : { AxeFx, AxeFx II, Gen Midi, No Bank, Eclipse } = aUser.cMidi.devtypes[ ]
  • Display Offset : { 0 or 1 } = aUser.cMidi.dispoffset[ ]
  • MIDI Channel : { 1 .. 16} = aUser.cMidi.chans[ ]
  • Lemur Target : { 0.. 3 } = aUser.cMidi.targets[ ]

The user can select one of A,B,C, or D target devices; only one is active at a time.

The objective is to integrate AxeFxXL and AxeFxXL+ into the list of supported Device Types.

Since this template was last updated by David Sorlien, two new AxeFx devices have been created. The XL and XL+ have more or less the same SysEx protocols as the AxeFx ( subject to change ), but have New SysEx device ID codes. The following is a break down of work required to make AxeForLemur support other Fractal Audio Devices.

Essentially the T1/cTargets/swSettings is a 4 x 4 Switch matrix. Pressing a button will provide a 0..16 button index within the T1/cTargets/swSettings/x variable. Pressing one of the T1/cTargets/padUpDn will cause the selected T1/cTargets/swSettings/x indexed value to be Incremented/decremented. The padUpDn/tap() changesbutton matrix.

Add two more values to devtypes

   aUser.cMidi.devtypes[a] = clamp(aUser.cMidi.devtypes[a]+1, 0, 4);
   aUser.cMidi.devtypes[a] = clamp(aUser.cMidi.devtypes[a]-1, 0, 4);
   aUser.cMidi.devtypes[a] = clamp(aUser.cMidi.devtypes[a]+1, 0, 6);
   aUser.cMidi.devtypes[a] = clamp(aUser.cMidi.devtypes[a]-1, 0, 6);

Add two more strings to button objet lablels

   if(aUser.cMidi.devtypes[i]==0) a[i] = 'AxeFX';
   else if(aUser.cMidi.devtypes[i]==1) a[i] = 'AxeFX II';
   else if(aUser.cMidi.devtypes[i]==2) a[i] = 'Gen MIDI';
   else if(aUser.cMidi.devtypes[i]==3) a[i] = 'No Bank';
   else if(aUser.cMidi.devtypes[i]==4) a[i] = 'Eclpse';
   else if(aUser.cMidi.devtypes[i]==5) a[i] = 'AxeXL';
   else if(aUser.cMidi.devtypes[i]==6) a[i] = 'AxeXL+'; }

Change Device ID's within SysEx messages to include devie ids { 6 and 7 }

 <SCRIPT name="IsAxeSysex(msg)" ..
 if(msg[0]==0 && msg[1]==1 && msg[2]==0x74 && ( msg[3]<=3 || msg[3]==6 || msg[3]==7 )
 else if(msg[3]==3) st = 'Axe-FX II';
 else if(msg[3]==6) st = 'Axe-FX XL';
 else if(msg[3]==7) st = 'Axe-FX XL+';

and change all hard coded device id's "0x74,3" with "0x74,6" or "0x74,7" in

 SendSetParam(b, p, v)
 SendGetParam(b, p)
 SendSetModifier(b, p, m, v)
 SendGetModifier(b, p, m)
 SendPlaceEffect(b, pos, flag)
 SendConnectEffect(p1, p2, f)
 SendSavePatch(program, bank)

It makes sense to define a class variable like cV.DevID, and make sure it is set on startup by the AxeFx device ID selected by the A,B,C,D device selector.

Design Modifiers

Modifiers provide a means to dynamically change a subset of the block parameters with automatic, and external functions. The AxeToLemur Script has a partial implementation of Modifiers. The AxeToLemur.pdf describes 'double tapping' the intended modify-able' control to enable modifier, but this doesn't appear to be within the implementation.

Within the 'control's bps[] array, for hw==0, element at index==6 is the Modifier number, if this value is >= 0, then the control should have modify-able values. This applies to 'bps' of sliders, custom buttons, muxed-sliders. If the 'control's bps[8] is set to 1, then there is an active modifier on the control.

It is assumed that 'double tapping' the 'Zoom' button will enable a RED "MOD" feature on the Zoom button. cS.DoubleTap() captures double tap event. This sets cV.dbltapzoom[2] = 1; A parameter that is 'Modify-able' has a Green 'txt' value.

As of 3.08, the repainting logic within the APP did not support GREEN 'txt' labels.

cS.psmxfdr(obj, p, p, m, t), and cS.psmxcb(obj,b,p,m,t) used to set/map a 'muxed fader' to an AxeFx control. This function also sets the colour of the text of a control


ResetModifierText(..), called when changing pages in Lemur, to clear out cV.modlistlast

(cV.rState==5) modifiers are being queried SendGetModifier(..)

(cV.rState==6) modifiers are being queried SendGetModifier(mbps[hw], mbps[hw+6], a[i]); response in HandleModifierValMsg(msg), calls UpdateModifier(b, p, m, v);

(cV.rState==7) modifiers are being reset SendSetModifier(..)

buildModCtlList() saves cV.modlist[] to cV.modlistlast[], iterates through all objects in cMain. To find build a cV.modlist[] of modifyable parameters within objects that 1. contain a bps[], 2. are in a visible block, 3. the block is active in the preset, the bps[6] is >= 0. cV.dbltapzoom[] is filled with same array of objects

cS.DoubleTap() appears to be implemented to open a Modifier Dialog: dlgModifiers.showme(1); but it is not called within the Script. This function will trigger a 'DoEveryFrame' midi query of the Modifier setting.

3.09 TODO List:

1. confirm all modifier indexes on Fractal Parameters

2. call cS.DoubleTap() when Zoom == MOD and a modifyable control is Tapped.

3. verify control's txt value is rendered RED when control modified control is active (previously engaged, polled through DoEveryFrame())

Project Globals

Var blkd=

Var blksq=

Var blok=

Var blx=

Var debugflag=

Var hw= 'hardware version =0 AxeFx, =1 others, Ultra etc.

Var Querying=


Script BuildParamList()

Sets cV.bpobj to first object in cMain, and iterates through all objects to build cV.BlocksToRefresh list. For Block numbers (99..200) that are in the preset values are added to a refresh list

Script RefreshSequencer()

Script SendCCAxe(ccnum, ccval)

Script SendConnectEffect(p1, p2, f)

Script SendGetByState()

Script SendGetCabName(cabnum)

Script SendGetModifier(b, p, m)

Script SendGetParam(b,p)

Script SendGetPresetName()

Script SendGetPresetNumber()

Script SendGetRoutingGrid()

Script SendGetSceneState()

Script SendLooperMonEn(en)

Script SendPG2Axe(pgnum)

Script SendPlaceEffect(b,pos,flag)

Script SendSavePath(program, bank)

Script SendSetModifier(b, p, m, v)

Script SendSetParam(b, p, v)

Script SendSetPresetName(name)

Script SynthMidiNoeOffIn(MIDI_ARGS)

Script SynthMidiNoteOnIn(MIDI_ARGS)

Script sxoutHandler(b,p, s, val)

Script UserMidiCCIn(MIDI_ARGS)



Major AxeForLemur Objects:


User specific settings, like favorite presets, midi channel. These can be persistent if the user re-saves the script after mondifications are made through the script itself. Global midi CC's are stored in*

Querying : set to 1 during referesh, most likely to prevent re-triggering

aUser.cMidi.gen2 :: MIDI CC # numbers for different MIDI CC parameters

..scenescc[0]  : MIDI CC # number for 'scene select'


User interface for Axe-Fx blocks.

cMain contains UI design and configuration for each Block (pair) Tab within AxeForLemur script

IntState3(..) macro, configures button labels within the UI interface. Typically these buttons are for Block instance selection, but some are for selecting other aspects of each' block Tab.

Each AxeForLemur Block Tab contains multiple containers, one for each UI element. These containers more or less contain a symetrical set of attributes, functions and UI controls that allow for support from a common set of functions (else where in the code).

Each UI Element contains:
 bps: Midi / UI control structure
 ctl: the lemur screen object
    x : Primary value for this control
    z : ???
 txt:  A screen description of the parameter. Example ('volume')
 txtval: text object on screen to describe the object parameter value.  Example (0..127)
    cbDlg: a pop up dialog object
       x : value for the selected value of the dialog
       tap(..) : function called to initialize the dialog

When a control changes a 'magic' must be called to send the ctl's value to the bps[..] defined midi destination


Common Scripting Object.

Common Script Object Container

addRefreshParam( b, p) : Adds a parameter to one of:

 (cV.blist[0..249],    cV.plist[0..249]), 
 (cV.blist2[250..499], cVplist2[250..499]), 
 (cV.blist3[500..749], cV.plist3[500..749]) at position cV.numcontrols, 

But doesn't appear to increase cV.numcontrols, called from Project.BuildParamList()

cS.psmxfdr(obj, b, p, -1, 'label')


AxeForLemur cShow

Group of scripts to refresh Axe Block Tabs.



Group of global variables.

blist, plist, blist2, plist2, blist3, plist3 250 entry lists of active 'b==block id's and p==parameter ids. each list has a physical limit of 250 elements. These 6 arrays constitute a 2D array of 750 items.

AxeForLemur ...

Pop Up Dialogs.

Lesser Objects (for now)

cbHideRoutes :

cbHideRoutes :

cbProgName : Button on bottom of UI to display dlgProgChange.showme(x)

cbRefresh :

cbTapTempo : Sends a CC 14 value 127 to currently selected Axe target, method cbTapTempo.hdlSxin(..) sets the lemur Tap button different colors

cbZoom: A double tap 'Zoom' function for sliders, dont know how this works.


Global Functions


Development Tools

firstobject XML Editor Application. This is a light weight free XML editor that doesnt get confused by the Lemur script. The Editor has a good dual view ( one view is an XML object tree, the other side is the pure text. Using F7 allows you to sync between the two.

KDIFF3 Since the AxeForLemur is a large monolithic text file, having a good DIFF tool allows you to see the changes LemurEditor and text editors have applied to your file. The LemurEditor does some strange things to this template when it is edited, the preference is to make clean edits with FirstObject Editor, and not use the Lemur Editor directly, as it has a habit of changing many unintended parameters throughout the script.

SVN or Git are good tools to manage progressive changes to the script.

Releases and Resources