MIDI Remote: How can I program a pitch-bend filter for just ONE device?

Hello everyone,

I wonder if somebody can help me on this.

I have a very old M-Audio Keystation keyboard. With time (and dust, and me opening it up and screwing the neutral position of the wheel) my pitchbend wheel started outputting unwanted pitchbend changes.

As everything else is fine, I’m trying to write a “filter” for the pitchbend, which I can use from another MIDI Remote.

I did the following hacky attempt, but it doesn’t work. It seems that “setProcessValue” is just called somewhere down the line but doesn’t impact the PB message already received.

Also, I know about the Input Transformer - I just don’t want to go in my 400 tracks template and change the input transformer line by line. And I don’t want to filter Pitchbend on ALL incoming devices either. I have a TouchOSC template that can effectively send and receive, and I want to use that instead.

Any help? Thanks!!!

var PitchBendWheel = surface.makeLamp(0, 0, 1, 1)


PitchBendWheel.mSurfaceValue.mOnProcessValueChange = function (activeDevice, value, units) {

    if (value != 0.5) {

        console.log("Detected PB Change: " + (Math.floor(value*127)).toString())
        PitchBendWheel.mSurfaceValue.setProcessValue(activeDevice, 0.5)


A way to do this is to use another MIDI port (I’m using loopMIDI for such things) and upon the mOnProcessValueChange (Since you’ve stated that this works), sendMIDI to this new port. Since it is a loop port, it will pass it back to Cubase.

1 Like

A couple of things come to mind.

  1. You mentioned the transformers.

Did you use a ‘global’ one, or individual track inserts? Up through Cubase 12, I think there is a set of 4 parallel ‘global’ or ‘local’ Track Input Transformers. The global one can remain active by default for all tracks, all the time by simply ticking active the tracks that need it and choosing ‘global’. The ‘local’ ones can be different on a track by track basis.

Cubase 12 has a new ‘project transformer’.

  1. If you don’t already have one, install a virtual MIDI port (personally I like loopMIDI on Windows…and I think Macs have it built into the OS).

From there you can use an empty MIDI track with Monitoring enabled to set up filters, MIDI mods, transformers, etc. Your routing would be: Controller > MIDI track with channel set ANY > Virtual Port > tracks that require this processed MIDI stream as their input. Using empty MIDI tracks like this makes it easy to set up all kinds of MIDI routing/processing alternatives. You can even have several different ones and swapping among them is as easy as toggling the monitor buttons.

Such ‘routing/processing’ tracks could also be routed into scripted remotes.

1 Like

Thanks for your input - obviously my end result would have been to create a customizable software filter with no 3rd parties, as I’m always scared by introducing latency with the every middleman - but I do have loopMIDI installed so this could be a solution.
I also tried to set up two output ports instead of one: one midiOutput and one midiFilter - sending to midiFilter all the unwanted stuff via sendMIDI - but alas, it still goes through.
This is also just a hunch, but I think the “ALL Midi Inputs” setting is screwing me up as well.
I’ll do some further testing.

Ah, yes that can annoying. The Steinberg engine grabs all the ports it can when launched!

For Cubase Pro and Nuendo, I think there is a way to blacklist specific ports somewhere in the studio setup if you really need that. In contrast, Dorico (and maybe some of the smaller versions of Cubase) just grab it all at launch (Dorico can ‘mute’ what comes in from a give port, but the engine still grabs it!).

I have some controller with old USB>MIDI drivers that simply are not ‘multi-client’ compatible. My fix for those is to always launch something like Bidule or Bome first…then route it over to a virtual port.

Since I often need to pop open more than one HOST on the same system…I’ve just arranged to have a stand alone instance of Bidule launch every time my Windows boots. I do a bit of MIDI processing there before anything ever hits the DAW. In fact, I once had a flaky pitch bend wheel that sent random events. It was my temp fix to filter it there (till I could order a replacment part). I also had some sticky keys once on a controller…they were way low on the keyboard so not used all that often. I could just ‘filter them out’ until I had a chance to make the repairs.

I also take advantage of the OSC server/client in Bidule to bring junk in from my Android devices over the WAN.

1 Like

Thank you.
Yes I know about the Input Transfomers and the Project Input Transformer.

The issue I have with the conditions option in the Project input transformer is that you cannot “filter by device” - because I want to use pitchbend via TouchOsc, not entirely wipe out Pitchbend data.

Another issue is that sadly I need to have “All MIDI Inputs” set on a track if I want to control notes via MIDI keyboard and CCs via TouchOSC - that is not ideal as I’m an idiot and I programmed some Macros to correspond to Note ON buttons :stuck_out_tongue: but I am also lazy and don’t want to reprogram TouchOSC (the editor is a pain in the ass sometimes).

Your 2nd solution (one MIDI track acting as a filter and then sending to loopMIDI) sounds fun and intuitive, I’m definitely going to use it in the short term, also because for some unfathomable reason the Project Input Transformer is not working for me! I must have missed an obscure setting somewhere (…help?..).

My long term “project” still remains, though: this would be beneficial even to create a MIDI Remote controller that accepts more than one input and combines them.

I tried sending all unwanted stuff to a dedicated output port in the MIDI Remote, but that didn’t work. Again - it might be because of the “ALL MIDI Inputs” settings. I’ll do further testing.

Sounds like you might really like Bidule. Build it all in one place, then it’s good for ‘all your hosts’. Jump from Cubase, to Finale/Sibelius/Repaer/Whatever…and not have to reinvent the wheel in every environment :wink:

Monitoring and manipulating MIDI streams in real time is only the beginning of what it can do!

It does include OSC server/client. Touch should be able to communicate with it directly.

Again, MIDI is only the beginning. It does audio too! It’ll also host instrument and effect plugins :slight_smile:

Rewire support (As master or slave) is there if you still have a DAW that takes advantage of that.

Register it, and it’ll even run AS a plugin. Unlimited ways to host multiple effects and instruments in a single plugin slot (instrument or effects).

It’ll also be my bridge to still run VST2 plugins (if absolutely necessary) after Cubase fully ‘pulls the plug’ on VST2 support. I’m not holding my breath that some of my most used and loved instruments will ever see a proper VST3 version :frowning:

I did try Plogue Bidule way, way back and among other things it would allow you to layer instruments in a way that would use only one MIDI track. Huge thing when I was on Cubase Elements. :stuck_out_tongue:

1 Like

Of all the plugins or DAW supplements I’ve ever owned, it is hands down the most used. Has paid for itself many times over.

I call it my Swiss Army knife plugin.

It sits at the foundation in stand alone mode, in tandem with ASIOLink Pro as a ‘patch bay’ center.

If a host can’t do it on its own…bidule comes to the rescue :slight_smile:

Also nice that I can port entire setups among different Hosts/DAWs without having to ‘rebuild’ it from scratch for each one. Can port over very complicated instrument and effect setups, or even share them ‘server style’ (from a different machine with something like rtpMIDI, and ASIO Link Pro, or reaStream) :slight_smile:

I also enjoy that if I have a situation where I need to ‘add/remove/change’ plugins while the DAW transport is going, I can do it from inside a Bidule instance without ‘audio glitches’. Comes in handy if I’m performing live on stage, or doing something over a live stream (Always keep an FX track with an empty instance on the ready for effects, and an empty instance or two in the instrument rack).

1 Like

Well I’m a heavy Vienna Ensemble Pro user, so for the patch/fx aspects… I’m covered.

This here was just an attempt for me to learn how the MIDI Remote API “treats” incoming signals, because if the MIDI messages go through it before reaching the midi Output, then of course it can act as a filter.

I just want to know how to block something in the Remote API, because at the moment I don’t seem to be able to block the flow :slight_smile:

1 Like

I think I have found a solution to the initial problem: filtering PB wheel by device.

Provided that “All MIDI inputs” is deactivated, this works in Nuendo 12:

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

var PitchBendWheel = []

for(i=0;i<16;++i) {

    PitchBendWheel[i] = surface.makeCustomValueVariable('PB_'+i.toString())
    PitchBendWheel[i].mOnProcessValueChange = function (activeDevice, value1, value2) {
        // midiFilter.sendMidi(activeDevice, value1) --- THIS ONLY IF YOU WANT TO RETAIN PitchBend DATA, otherwise you can just leave an empty function!


1 Like

A way to do this is to use another MIDI port (I’m using loopMIDI for such things) and upon the mOnProcessValueChange (Since you’ve stated that this works), sendMIDI to this new port. Since it is a loop port, it will pass it back to Cubase.

This actually worked.
Initially I created a 2nd dummy output for just the filtered values and used sendMIDI() there.

But actually just removing any code in the mOnProcessValueChanged function actually works.

Now I’m left with the opposite dilemma of how to use pitchbend from TouchOSC. I think I’ll have to use loopMIDI eventually.


Sorry everybody,

this actually did not work. It works, for some unexplicable reason, on Instrument tracks (hence my eureka moment), but not on MIDI tracks.

I’m going to do further tests.

EDIT: Found why it’s happening.
Cubase/Nuendo, if the channel is X, already routes pitchbend to be on channel X even if the keyboard itself has it on channel 1. Listening and excluding all 16 channels makes it work.

@Jochen_Trappe why does this above with “makeCustomValueVariable” work, but if I change that to a simple element like a lamp, and do a “normal” mSurfaceValue.mMidiBinding it doesn’t work?

I wasn’t able to make it work with nothing but the Custom Value Variable - but it screws the layout of the display, as when I do that. nothing else comes on the surface layout page apart for some weird stuff.