MidiBindingToNote (off)

How do I bind to NoteOff in remote script? In midi note-on and note-off is two separated messages. I expect to get both note-on and note-off with MidiBindingToNote and a method to separate them. But I can not find any.

Hi @cubace, MidiBindingToNote binds to note-on, note-off and poly-pressure.

You can use the custom variable value feature like this:

var onOffSplitter1 = surface.makeCustomValueVariable('NoteOnOffSplitter1')
onOffSplitter1.mMidiBinding.bindToNote(0, 48)

var onValue1 = surface.makeCustomValueVariable('OnValue1')
var offValue1 = surface.makeCustomValueVariable('OffValue1')

onOffSplitter1.mOnProcessValueChange = function (activeDevice, value, diff) {
    var isNoteOn = value > 0 && diff === value
    var isNoteOff = value === 0 && diff < 0
    if (isNoteOn) {
        onValue1.setProcessValue(activeDevice, 1)
        offValue1.setProcessValue(activeDevice, 0)
    }
    else if (isNoteOff)
    {
        onValue1.setProcessValue(activeDevice, 0)
        offValue1.setProcessValue(activeDevice, 1)
    }
}

page.makeValueBinding(onValue1, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mMute)
page.makeValueBinding(offValue1, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mSolo)

I does not work.
I do a cut&past of the snippet. It seems not to run though so I add console.log and
sees that after the “var onOffSplitter1 = surface.makeCustomValueVariable(‘NoteOnOffSplitter1’)”
No console.log messages are show. Are surface some global object that is given?

sorry, surface is:

var surface = deviceDriver.mSurface

btw: The snippet is for explanation and not for c&p :wink:

But it would be easier to understand if they worked :wink:

//-----------------------------------------------------------------------------
// 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('test', 'noteon', 'no')

// 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('SimpleDevice IN')
    .expectOutputNameEquals('SimpleDevice OUT')
    
deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput)
    .expectInputNameEquals('SimpleDevice (MIDI IN)')
    .expectOutputNameEquals('SimpleDevice (MIDI OUT)')


//-----------------------------------------------------------------------------
// 2. SURFACE LAYOUT - create control elements and midi bindings
//-----------------------------------------------------------------------------

// create control element representing your hardware's surface
var knob1 = deviceDriver.mSurface.makeKnob(0, 0, 1, 1.5)
var knob2 = deviceDriver.mSurface.makeKnob(1, 0, 1, 1.5)
var knob3 = deviceDriver.mSurface.makeKnob(2, 0, 1, 1.5)
var knob4 = deviceDriver.mSurface.makeKnob(3, 0, 1, 1.5)

// bind midi ports to surface elements
knob1.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToNote (0, 80) // channel 0, cc 21

knob2.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToNote (0, 81) // channel 0, cc 22

knob3.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToNote (0, 83) // channel 0, cc 23

knob4.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToNote (0, 84) // channel 0, cc 24

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

// create at least one mapping page
var page = deviceDriver.mMapping.makePage('Example Mixer Page')

// create host accessing objects
var hostSelectedTrackChannel = page.mHostAccess.mTrackSelection.mMixerChannel

// bind surface elements to host accessing object values
page.makeValueBinding(knob1.mSurfaceValue, hostSelectedTrackChannel.mValue.mVolume)
page.makeValueBinding(knob2.mSurfaceValue, hostSelectedTrackChannel.mSends.getByIndex(0).mLevel)
page.makeValueBinding(knob3.mSurfaceValue, hostSelectedTrackChannel.mSends.getByIndex(1).mLevel)
page.makeValueBinding(knob4.mSurfaceValue, hostSelectedTrackChannel.mSends.getByIndex(2).mLevel)

var surface = deviceDriver.mSurface
var onOffSplitter1 =  surface.makeCustomValueVariable('NoteOnOffSplitter1')
onOffSplitter1.mMidiBinding.setInputPort(midiInput).setOutputPort(midiOutput).bindToNote(0,82)

var onValue1 = surface.makeCustomValueVariable('OnValue1')
var offValue1 = surface.makeCustomValueVariable('OffValue1')

onOffSplitter1.mOnProcessValueChange = function (activeDevice, value, diff) {
    var isNoteOn = value > 0 && diff === value
    var isNoteOff = value === 0 && diff < 0
    console.log("vc")
    if (isNoteOn) {
        onValue1.setProcessValue(activeDevice, 1)
        offValue1.setProcessValue(activeDevice, 0)
        console.log("on")
    }
    else if (isNoteOff)
    {
        onValue1.setProcessValue(activeDevice, 0)
        offValue1.setProcessValue(activeDevice, 1)
        console.log("off")
    }
}

page.makeValueBinding(onValue1, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mMute)
page.makeValueBinding(offValue1, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mSolo)

console.log('done')

Works fine for the knobs but no callback on split function. Some more binding needed?

Did you check the Script Console Window for any errors?

It is the same console that is supposed to write my console.log messages? Yes then…
It is load until done and the input is from my yamaha keyboard.
correction The key that is supposed to be split are consumed.

try this:

var hostDummyValue1 = page.mCustom.makeHostValueVariable('HostDummyValue1')
page.makeValueBinding(onOffSplitter1, hostDummyValue1)

Did not help. No print from the split.

Can you temporarily change the knob4 midi binding to “.bindToNote (0, 82)” to check if note 82 on Channel 1 is working at all, please?

That work fine.

Im trying doing the absolutely smallest change to get function called.
I think this is it:

knob4.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .setOutputPort(midiOutput)
    .bindToNote (0, 84) // channel 0, cc 24
    .mOnProcessValueChange = function (x, y ,z) { 
        console.log('myfunc')
    }
    

I still does not get any log messages.

If I try to add the mOnProcessValueChange on mSurfaceValue like this

knob2.mSurfaceValue.mOnProcessValueChange = function (x, y ,z) {
    console.log("knob2")
    console.log(x.toString())
    console.log(y.toString())
    console.log(z.toString())
}
knob3.mSurfaceValue.mOnProcessValueChange = function (x, y ,z) {
    console.log("knob3")
    console.log(x.toString())
    console.log(y.toString())
    console.log(z.toString())
}
knob4.mSurfaceValue.mOnProcessValueChange = function (x, y ,z) {
    console.log("knob4")
    console.log(x.toString())
    console.log(y.toString())
    console.log(z.toString())
}

I get some response. But I get response on all knobs.
This is the output for one keypress and a keyrelease

knob2
[object Object]
0
0
knob3
[object Object]
0.5118110179901123
0
knob4
[object Object]
0
0
knob3
[object Object]
0.5118110179901123
0
knob2
[object Object]
0
0
knob3
[object Object]
0.5118110179901123
0
knob4
[object Object]
0
0




knob3
[object Object]
0
-0.5118110179901123
knob2
[object Object]
0
0
knob3
[object Object]
0
0
knob4
[object Object]
0
0
knob3
[object Object]
0
0
knob2
[object Object]
0
0
knob3
[object Object]
0
0
knob4
[object Object]
0
0

Im getting confused.

please remove the “setOutputPort”. Maybe the device pingpongs the messages back.
The first parameter of the callback is the “activeDevice” handle. That’s why it says “[object Object]”.

Im not confused by the content of the parameters, im confused that knob2 also get knob3 events. Removing the SetOutputPort did not change anything.

mOnProcessValueChange is called by the ValueBinding as well (from the host side). That explains the additional (unexpected) calls.

As I read this code this checks for NoteOn Value = 0 as note off.
This is not the same thing as a NoteOff message.
NoteOn is 0x9c and NoteOff is 0x8c.

“bindToNote(0, 48)” binds all three message types: note-on, -off, and poly-pressure.

I get some response for both NoteOn and NoteOff with binding.
But when I send NoteOff value of any valid number for that key I get value=0 and diff=0
with console.log(value.toString()) and console.log(diff.toString()) in the first line of the function.

When monitor with a midi insert they show up right.
And you will also need to be able to differentiate NoteOff key:value=0 from NoteOn key:value=0.

yes, we ignore note-off velocity.