Akai Advance 25 midi remote Script

Hi!
here is a small script i made for AKAI Advance 25 with simple assignments.

as the knobs are 360 degree infinite rotation I would like it to update directly according to the selected track like the motorized fader

so i need help as i am not an experiamenter developer and the api is not really documented yet because it is still young

//-----------------------------------------------------------------------------
// 1. DRIVER SETUP - create driver object, midi ports and detection information
//-----------------------------------------------------------------------------

// get the api's entry point
var midiremote_api = require('midiremote_api_v1')

// create the device driver main object
var deviceDriver = midiremote_api.makeDeviceDriver('Akai', 'Advance 25', 'Gnox')

// create objects representing the hardware's MIDI ports
var midiInput = deviceDriver.mPorts.makeMidiInput()
var midiOutput = deviceDriver.mPorts.makeMidiOutput()

// define all possible namings the devices MIDI ports could have
// NOTE: Windows and MacOS handle port naming differently
deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput)
    .expectInputNameEquals('ADVANCE25 USB PORT 1')
    .expectOutputNameEquals('ADVANCE25 USB PORT 1')
    
//deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput)
//   .expectInputNameEquals('SimpleDevice (MIDI IN)')
//    .expectOutputNameEquals('SimpleDevice (MIDI OUT)')

var surface = deviceDriver.mSurface

//---------- channelNumber and controlChangeNumber -----------//
// KnobcNr = knobIndex
const KnobccNr = 7
// switcheccNr = switcheIndex 
const switcheccNr = 65
const padcNr = 15
const padInitPitch = 36
const transportcNr = 0
const transportccNrs = [118, 119, 117, 114]
//-----------------------------------------------------------------------------
// 2. SURFACE LAYOUT - create control elements and midi bindings
//-----------------------------------------------------------------------------

// Encoders
function makeKnobStrip(knobIndex, x, y) {
    var knobStrip = {}
    
    knobStrip.knob = surface.makeKnob(x * knobIndex + 16.5, y, 2.5, 2.5)
    knobStrip.knob.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(knobIndex, KnobccNr)

    return knobStrip
}

// Switches
function makeSwitcheStrip(switcheIndex, x, y) {
    var switcheStrip = {}
    
    switcheStrip.button = surface.makeButton(x * switcheIndex + 17, y, 1.5, 0.8)
    switcheStrip.button.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(switcheIndex, switcheccNr)

    return switcheStrip
}

// Pads
function makePadStrip(padIndex, x, y) {
    var padStrip = {}
    
    padStrip.pad = surface.makeTriggerPad(x * padIndex + 16.5, y, 2.5, 2.5)
    padStrip.pad.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToNote(padcNr, padInitPitch + padIndex)

    return padStrip
}

// Transport Control Buttons
function makeTransport(transportIndex, x, y, ccNr) {
    var trasnport= {}
    
    trasnport.button = surface.makeButton(x * transportIndex + 29, y, 1.5, 1)
    trasnport.button.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(transportcNr, ccNr)

    return trasnport
}

function makeSurfaceElements() {
    var surfaceElements = {}

    surfaceElements.numStrips = 8
    surfaceElements.numTransport = 4

    // Encoders
    var x = 2.5
    var y = 0
    surfaceElements.knobStrips = {}
    for(var i = 0; i < surfaceElements.numStrips; ++i) {
        surfaceElements.knobStrips[i] = makeKnobStrip(i, x, y) 
    }

    // Switches
    x = 2.5
    y = 2.8
    surfaceElements.switcheStrip = {}
    for(var i = 0; i < surfaceElements.numStrips; ++i) {
        surfaceElements.switcheStrip[i] = makeSwitcheStrip(i, x, y)
    }

    // Pads
    x = 2.5
    y = 4
    surfaceElements.triggerPads = {}
    for(var i = 0; i < surfaceElements.numStrips; ++i) {
        surfaceElements.triggerPads[i] = makePadStrip(i, x, y)
    }

    // Transport Control Buttons
    x = 1.9
    y = 7
    surfaceElements.trasnport = {}
    for(var i = 0; i < surfaceElements.numTransport; ++i) {
        var ccNr = transportccNrs[i]
        surfaceElements.trasnport[i] = makeTransport(i, x, y, ccNr)
    }

    // Pitch-Bend Wheel
    var pitchBend = surface.makePitchBend(1.5, 10, 1.5, 6)
    pitchBend.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToPitchBend(0)

    // Modulation Wheel
    var modWheel = surface.makeModWheel(5, 10, 1.5, 6)
    modWheel.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToControlChange(0, 1)


    //----------------unassignable buttons---------------//
    x = 1.9
    y = 5.7
    var w = 1.5
    var h = 0.8
    var xOffset = 2.9

    // Page Left/Right
    for (var i = 0; i < 2; i++) {
        surface.makeBlindPanel(x * i + xOffset, 5.7, w, h)
    }

    // Shift and Mode Buttons
    y = 7.2
    xOffset = 0
    for (var i = 0; i < 7; i++) {
        if (i >= 5) {
            xOffset = 3.2
        }
        surface.makeBlindPanel(i * x + xOffset, y, w, h)
    }

    // Octave Down/Up, Arp / Config, Latch, Tap Tempo, Note Repeat and Full Level
    y = 7
    h = 1
    xOffset = 16.5
    for (var i = 0; i < 5; i++) {
        surface.makeBlindPanel(i * x + xOffset, y, w, h)
    }
   
    surface.makeBlindPanel(0.5, 0, 8, 5).setShapeRectangle()    // Display
    surface.makeBlindPanel(10.1, 0, 2.6, 2.6).setShapeCircle()   // Data Dial

    // Cursors
    surface.makeBlindPanel(9.65, 2.8, 1.15, 2.2)
    surface.makeBlindPanel(10.65, 2.8, 1.5, 1.15)
    surface.makeBlindPanel(10.65, 3.85, 1.5, 1.15)
    surface.makeBlindPanel(12, 2.8, 1.15, 2.2)

    surface.makeBlindPanel(14.6, 2.8, 1.5, 0.8)     // Time Div
    surface.makeBlindPanel(14.6, 5.7, 1.5, 0.8)     // Pad Bank
    surface.makePianoKeys(7.5, 8.5, 29, 10, 0, 24)  // Keyboard

    return surfaceElements
}

var surfaceElements = makeSurfaceElements()

//-----------------------------------------------------------------------------
// 3. HOST MAPPING - create mapping pages and host bindings
//-----------------------------------------------------------------------------

var switches = surfaceElements.switcheStrip
var trasnports = surfaceElements.trasnport
var pads = surfaceElements.triggerPads
var knobs = surfaceElements.knobStrips

function makePage(name) {
    var page = deviceDriver.mMapping.makePage(name)

    page.makeActionBinding(switches[6].button.mSurfaceValue, page.mHostAccess.mTrackSelection.mAction.mPrevTrack)
    page.makeActionBinding(switches[7].button.mSurfaceValue, page.mHostAccess.mTrackSelection.mAction.mNextTrack)

    page.makeValueBinding(trasnports[0].button.mSurfaceValue, page.mHostAccess.mTransport.mValue.mStart)
    page.makeValueBinding(trasnports[1].button.mSurfaceValue, page.mHostAccess.mTransport.mValue.mRecord)
    page.makeValueBinding(trasnports[2].button.mSurfaceValue, page.mHostAccess.mTransport.mValue.mStop)
    page.makeValueBinding(trasnports[3].button.mSurfaceValue, page.mHostAccess.mTransport.mValue.mCycleActive)

    return page
}

function makePageSelectedTrack() {
    var page = makePage('Selected Track')
    var selectedTrackChannel = page.mHostAccess.mTrackSelection.mMixerChannel

    for (var i = 0; i < 8; i++) {
        page.makeValueBinding(knobs[i].knob.mSurfaceValue, selectedTrackChannel.mQuickControls.getByIndex(i)).setValueTakeOverModeScaled()
    }

    page.makeValueBinding(switches[0].button.mSurfaceValue, selectedTrackChannel.mValue.mMute).setTypeToggle()
    page.makeValueBinding(switches[1].button.mSurfaceValue, selectedTrackChannel.mValue.mSolo).setTypeToggle()
    page.makeValueBinding(switches[2].button.mSurfaceValue, selectedTrackChannel.mValue.mMonitorEnable).setTypeToggle()
    page.makeValueBinding(switches[3].button.mSurfaceValue, selectedTrackChannel.mValue.mEditorOpen).setTypeToggle()
    page.makeValueBinding(switches[4].button.mSurfaceValue, selectedTrackChannel.mValue.mInstrumentOpen).setTypeToggle()

    return page
}

function makePageSelectedMixerChannel() {
    var page = makePage('Mixer')
    var selectedMixerChannel = page.mHostAccess.mTrackSelection.mMixerChannel
    
    page.makeValueBinding(knobs[0].knob.mSurfaceValue, selectedMixerChannel.mValue.mVolume).setValueTakeOverModeScaled()
    page.makeValueBinding(knobs[1].knob.mSurfaceValue, selectedMixerChannel.mValue.mPan).setValueTakeOverModeScaled()
    page.makeValueBinding(knobs[2].knob.mSurfaceValue, selectedMixerChannel.mSends.getByIndex(0).mLevel).setValueTakeOverModeScaled()
    page.makeValueBinding(knobs[3].knob.mSurfaceValue, selectedMixerChannel.mSends.getByIndex(1).mLevel).setValueTakeOverModeScaled()
    page.makeValueBinding(knobs[4].knob.mSurfaceValue, selectedMixerChannel.mSends.getByIndex(2).mLevel).setValueTakeOverModeScaled()

    page.makeValueBinding(switches[0].button.mSurfaceValue, selectedMixerChannel.mValue.mMute).setTypeToggle()
    page.makeValueBinding(switches[1].button.mSurfaceValue, selectedMixerChannel.mValue.mSolo).setTypeToggle()
    page.makeValueBinding(switches[2].button.mSurfaceValue, selectedMixerChannel.mSends.getByIndex(0).mOn).setTypeToggle()
    page.makeValueBinding(switches[3].button.mSurfaceValue, selectedMixerChannel.mSends.getByIndex(1).mOn).setTypeToggle()
    page.makeValueBinding(switches[4].button.mSurfaceValue, selectedMixerChannel.mSends.getByIndex(2).mOn).setTypeToggle()

    return page
}

var selectedTrack = makePageSelectedTrack()
var selectedMixerChannel = makePageSelectedMixerChannel()

selectedTrack.makeActionBinding(switches[5].button.mSurfaceValue, selectedMixerChannel.mAction.mActivate)
selectedMixerChannel.makeActionBinding(switches[5].button.mSurfaceValue, selectedTrack.mAction.mActivate)

selectedTrack.mOnActivate = function (context) {
	console.log('from script: AKAI Advance 25 "Selected Track" activated')
}

selectedMixerChannel.mOnActivate = function (context) {
	console.log('from script: AKAI Advance 25 "selected Mixer Channel" activated')
}

Advance 25.zip (2.5 KB)


Hi,

For the value binding, use the .setValueTakeOverModeJump ( instead of the .setValueTakeOverModeScaled()).

the problem with this method is that in cubase if I change track and I move the knob the volume fader will sooner recover the value of my controller. so if on my previous track I was at -12db and on the next track I’m at -4db if I move the knob the fader will find the position of -12db before being adjusted

Is there another way to send the fader value back to my controller to update it according to the track?

Hi,

Do you send any feedback to the hardware?

But the jump should solve it.