MIDI Remote API "Rounding errors"

Oh, I should have mentioned that a workaround is really straight-forward. Here’s a snippet which corrects the issue by using a pseudo fader. The idea is simple, we get the “real” fader’s value on its mOnProcessValueChange, round it properly and set the pseudo fader’s mSurfaceValue to this rounded one. In the testing I’ve done, I see no double triggers any more:

var midiremote_api = require('midiremote_api_v1')

var deviceDriver = midiremote_api.makeDeviceDriver('Issues', 'Rounding', 'Issues')

var midiInput = deviceDriver.mPorts.makeMidiInput("loopMIDI Port 1")
var midiOutput = deviceDriver.mPorts.makeMidiOutput("loopMIDI Port 2")

var detect = deviceDriver.makeDetectionUnit()

detect
    .detectPortPair(midiInput, midiOutput)
    .expectInputNameEquals("loopMIDI Port 1")
    .expectOutputNameEquals("loopMIDI Port 2")
    

var surface=deviceDriver.mSurface

var fader=surface.makeFader(0,0,1,5)
fader.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)    
    .bindToPitchBend(0)


var faderRounded=surface.makeFader(1,0,1,5)
faderRounded.mSurfaceValue.mMidiBinding
    .setInputPort(midiInput)
    .bindToPitchBend(1)

var page=deviceDriver.mMapping.makePage("page")

page.makeValueBinding(faderRounded.mSurfaceValue,page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mVolume).mOnValueChange=function(activeDevice,activeMapping,value,diff){
    
    console.log("got value="+value+" diff="+diff)
    console.log("time="+new Date().getTime())
    var value16383=Math.round(16383*value)
    console.log("got value16383="+value16383) //Not important, just for viewing purposes

    //let's convert this to binary with different precisions 
    console.log(decimalToBinary(value,32))
    console.log(decimalToBinary(value,24))
    //Seems to me that a rounding to 24 finally happens and retriggers the function

}

fader.mSurfaceValue.mOnProcessValueChange=function(activeDevice,value,diff){

    var round24Bin=decimalToBinary(value,24)

    var round24Dec=binaryToDecimal(round24Bin)

    faderRounded.mSurfaceValue.setProcessValue(activeDevice,round24Dec)

}

function decimalToBinary(fraction, precision) {
    
    var result = "."
    
    while (precision--) {
    
        fraction *= 2
    
        if (fraction >= 1) {
    
            result += "1"
            fraction -= 1
    
        } else {
    
            result += "0"
    
        }
    
    }
    
    return result

}

function binaryToDecimal(binaryFraction) {

    var fraction = binaryFraction.slice(1)
    
    var result = 0
    
    for (var i = 0; i < fraction.length; i++) {
    
        if (fraction[i] === '1') {
    
            result += Math.pow(2, -(i + 1))
    
        }
    
    }
    
    return result

}

Still, I don’t think this is the way to go, I mean to round before send. I believe this should be handled internally by the API.

3 Likes