MIDI over USB support

This has been mentioned before, but didn’t get much attention.

I would love to see support for MIDI control (e.g., fader levels, pan, FX sends) over USB, not just over TCP/IP. I think a lot of users—especially mobile performers using iOS apps like Loopy Pro—would benefit a lot from this. It means you can control the mixer directly in the app, which is extremely powerful.

I know there are potential workarounds using Mixing Station or other methods but they’re very hard to set up unless you’re a MIDI expert. Ethernet control is great for some users, but MIDI over USB is ideal in compact live setups where network routing isn’t feasible.

Thank you!!

Hello.
You can actually send midi over USB.
I use Stage traxx 3 and an IPAD connected directly to the CQ and I have the midi control for MUTE, scene change fader level etc.
The app recognize the CQ as a midi device automatically.
That should be the same for your app.
Tell us more about your issue so that we can help you.

Yup, @Frenchie is right - you can already do USB over MIDI.
The protocol is here: https://www.allen-heath.com/content/uploads/2024/10/CQ_MIDI_Protocol_V1_2_0_iss4.pdf
You may well need the MIDI control app from here: https://www.allen-heath.com/hardware/cq/cq-18t/resources/
(Don’t worry if you’ve got a different CQ - it’s the same app)
but iOS apps should be class compliant and just work. The CQ is locked to MIDI channel 1, if there’s the option to select that in the app.

@MarkF @frenchie thank you both — I completely missed that document on the website. It’s a huge help and got me 90% of the way there.

For anyone else trying to control the CQ-18T (or any CQ series mixer) from Loopy Pro, I was able to get it working by sending a Custom MIDI message using a string based on the Allen & Heath CQ MIDI Protocol v1.2.

For example, to control the pan/balance parameter of lp1 to (Main) LR, I entered the following string in Loopy Pro:

B0 63 50 B0 62 00 B0 06 xx B0 26 xx

xx represents a dynamic value tied to the current position of the widget (e.g., a dial or slider). This lets you control parameters like pan position directly from Loopy Pro’s UI.

For the fader/level of lp7 to (Main) LR you would enter:

B0 63 40 B0 62 06 B0 06 xx B0 26 xx

So far, this works perfectly for pan and level and presumably all similar NRPN-based parameters.

The only limitation is that Loopy Pro can’t read values from the CQ — for example, if you change a parameter on the mixer itself, Loopy Pro doesn’t update to reflect it. I tried using MIDI Learn in Loopy Pro, but it doesn’t understand NRPN sequences (which consist of a series of CC messages: CC99, CC98, CC6, CC38). As far as I can tell, Loopy can only MIDI Learn single CC or Note messages, not NRPN blocks.

I’ll reach out to the Loopy developer to request support for NRPN input, but I know they’re quite busy with other improvements at the moment so I’m not holding my breath.

If anyone figures out a good workaround for syncing values from the CQ into Loopy, I’d love to hear it. Thanks!

The only workaround I can think of would be to use a translator device like a Bome box in the mix - then all the MIDI goes via the other device which translates the NRPN from the mixer to whatever Loopy needs for those controls.

I have something that might help you but it is based on PC.
Tell me if that could interest you or not.

@MarkF @frenchie thank you guys again. You inspired me not to give up and I’ve finally got it working now.

I do have a Windows PC but wanted to keep everything between my iOS device and the mixer so after a few days of struggling, along with buying and playing around with bunch of third-party apps (MIDI Designer, MIDIFlow, MIDIFire and StreamByter - half of which didn’t work for me), I’ve finally found a workable solution for my setup. Hopefully it helps others get there a lot faster than it took me!

  1. Install MIDIFire and set up these two signal chains:

Chain 1: CQ18T (source) >> Event Monitor (optional - but useful for testing) >> Stream Byter - NRPN to CC (see code to install below) >> Event Monitor (optional - but useful for testing) >> Loopy Pro (destination)

Chain 2: Loopy Pro (source) >> Event Monitor (optional - but useful for testing) >> Stream Byter - CC to NRPN (see code to install below) >> Event Monitor (optional - but useful for testing) >> CQ18T (destination)

Make sure you copy and paste (and install) the code below in the respective Stream Byter modules before proceeding to step 2!

  1. Use MIDI Learn in Loopy Pro and adjust something on the CQ18T (or whatever NRPN device you’re using), but make sure it picks up the Virtual MIDI In (not any other devices which might populate if they reach Loopy first - you might have to do it quite a few times to get the right one).

  2. (optional) Inside Loopy, go to Menu > Control Settings > Virtual MIDI In (under MIDI Devices) and set the Latency Compensation to 200 ms. I found some of the controls from Loopy to the CQ are super choppy without this.

Below is the code I used for Stream Byter. This should work for all Allen & Heath CQ series mixers but if you’re using a different NRPN device, you will almost certainly have to modify the code to suit. ChatGPT will be your friend here :wink:

Code for Stream Byter - NRPN to CC module in MIDIFire


# NRPN-to-CC conversion for CQ Mixer
# Levels: MSB 0x40 → Ch7, CC102 to CC117
# Pans:   MSB 0x50 → Ch8, CC102 to CC117
# Mutes:  MSB 0x00 → Ch9, CC102 to CC117

IF M0 == 0XB0
  # Identify MSB
  IF M1 == 0X63
    IF M2 == 0X40
      ASS K0 = 1 # Level
      ASS K2 = 0
      ASS K4 = 0
    ELSE
      IF M2 == 0X50
        ASS K0 = 0
        ASS K2 = 1 # Pan
        ASS K4 = 0
      ELSE
        IF M2 == 0X00
          ASS K0 = 0
          ASS K2 = 0
          ASS K4 = 1 # Mute
        ELSE
          ASS K0 = 0
          ASS K2 = 0
          ASS K4 = 0
        END
      END
    END
    BLOCK
  END
  
  # LSB (shared across all)
  IF M1 == 0X62
    ASS K1 = M2
    BLOCK
  END
  
  # Handle LEVEL and PAN via CC6
  IF M1 == 0X06
    IF K0 == 1
      IF K1 == 0X00
        SND 0XB6 0X66 M2 # CC102
        BLOCK
      END
      IF K1 == 0X01
        SND 0XB6 0X67 M2
        BLOCK
      END
      IF K1 == 0X02
        SND 0XB6 0X68 M2
        BLOCK
      END
      IF K1 == 0X03
        SND 0XB6 0X69 M2
        BLOCK
      END
      IF K1 == 0X04
        SND 0XB6 0X6A M2
        BLOCK
      END
      IF K1 == 0X05
        SND 0XB6 0X6B M2
        BLOCK
      END
      IF K1 == 0X06
        SND 0XB6 0X6C M2
        BLOCK
      END
      IF K1 == 0X07
        SND 0XB6 0X6D M2
        BLOCK
      END
      IF K1 == 0X08
        SND 0XB6 0X6E M2
        BLOCK
      END
      IF K1 == 0X09
        SND 0XB6 0X6F M2
        BLOCK
      END
      IF K1 == 0X0A
        SND 0XB6 0X70 M2
        BLOCK
      END
      IF K1 == 0X0B
        SND 0XB6 0X71 M2
        BLOCK
      END
      IF K1 == 0X0C
        SND 0XB6 0X72 M2
        BLOCK
      END
      IF K1 == 0X0D
        SND 0XB6 0X73 M2
        BLOCK
      END
      IF K1 == 0X0E
        SND 0XB6 0X74 M2
        BLOCK
      END
      IF K1 == 0X0F
        SND 0XB6 0X75 M2
        BLOCK
      END
    END
    
    IF K2 == 1
      IF K1 == 0X00
        SND 0XB7 0X66 M2
        BLOCK
      END
      IF K1 == 0X01
        SND 0XB7 0X67 M2
        BLOCK
      END
      IF K1 == 0X02
        SND 0XB7 0X68 M2
        BLOCK
      END
      IF K1 == 0X03
        SND 0XB7 0X69 M2
        BLOCK
      END
      IF K1 == 0X04
        SND 0XB7 0X6A M2
        BLOCK
      END
      IF K1 == 0X05
        SND 0XB7 0X6B M2
        BLOCK
      END
      IF K1 == 0X06
        SND 0XB7 0X6C M2
        BLOCK
      END
      IF K1 == 0X07
        SND 0XB7 0X6D M2
        BLOCK
      END
      IF K1 == 0X08
        SND 0XB7 0X6E M2
        BLOCK
      END
      IF K1 == 0X09
        SND 0XB7 0X6F M2
        BLOCK
      END
      IF K1 == 0X0A
        SND 0XB7 0X70 M2
        BLOCK
      END
      IF K1 == 0X0B
        SND 0XB7 0X71 M2
        BLOCK
      END
      IF K1 == 0X0C
        SND 0XB7 0X72 M2
        BLOCK
      END
      IF K1 == 0X0D
        SND 0XB7 0X73 M2
        BLOCK
      END
      IF K1 == 0X0E
        SND 0XB7 0X74 M2
        BLOCK
      END
      IF K1 == 0X0F
        SND 0XB7 0X75 M2
        BLOCK
      END
    END
    
    BLOCK
  END
  
  # Handle MUTES via CC38 (Data Entry LSB)
  IF M1 == 0X26
    IF K4 == 1
      IF K1 == 0X00
        SND 0XB8 0X66 M2
        BLOCK
      END
      IF K1 == 0X01
        SND 0XB8 0X67 M2
        BLOCK
      END
      IF K1 == 0X02
        SND 0XB8 0X68 M2
        BLOCK
      END
      IF K1 == 0X03
        SND 0XB8 0X69 M2
        BLOCK
      END
      IF K1 == 0X04
        SND 0XB8 0X6A M2
        BLOCK
      END
      IF K1 == 0X05
        SND 0XB8 0X6B M2
        BLOCK
      END
      IF K1 == 0X06
        SND 0XB8 0X6C M2
        BLOCK
      END
      IF K1 == 0X07
        SND 0XB8 0X6D M2
        BLOCK
      END
      IF K1 == 0X08
        SND 0XB8 0X6E M2
        BLOCK
      END
      IF K1 == 0X09
        SND 0XB8 0X6F M2
        BLOCK
      END
      IF K1 == 0X0A
        SND 0XB8 0X70 M2
        BLOCK
      END
      IF K1 == 0X0B
        SND 0XB8 0X71 M2
        BLOCK
      END
      IF K1 == 0X0C
        SND 0XB8 0X72 M2
        BLOCK
      END
      IF K1 == 0X0D
        SND 0XB8 0X73 M2
        BLOCK
      END
      IF K1 == 0X0E
        SND 0XB8 0X74 M2
        BLOCK
      END
      IF K1 == 0X0F
        SND 0XB8 0X75 M2
        BLOCK
      END
    END
    BLOCK
  END
END

Code for Stream Byter - CC to NRPN module in MIDIFIre

# CC-to-NRPN conversion for CQ Mixer
# LEVELS (Channel 7 → MSB 0x40, CC6)
IF M0 == 0XB6
  IF M1 >= 0X66
    IF M1 <= 0X75
      MAT I0 = M1 - 0X66
      SND 0XB0 0X63 0X40 # MSB
      SND 0XB0 0X62 I0 # LSB
      SND 0XB0 0X06 M2 # Data Entry MSB (value)
      SND 0XB0 0X26 0X00 # Data Entry LSB cleared
      BLOCK
    END
  END
END

# PANS (Channel 8 → MSB 0x50, CC6)
IF M0 == 0XB7
  IF M1 >= 0X66
    IF M1 <= 0X75
      MAT I0 = M1 - 0X66
      SND 0XB0 0X63 0X50
      SND 0XB0 0X62 I0
      SND 0XB0 0X06 M2
      SND 0XB0 0X26 0X00
      BLOCK
    END
  END
END

# MUTES (Channel 9 → MSB 0x00, CC38)
IF M0 == 0XB8
  IF M1 >= 0X66
    IF M1 <= 0X75
      MAT I0 = M1 - 0X66
      SND 0XB0 0X63 0X00
      SND 0XB0 0X62 I0
      SND 0XB0 0X26 M2 # Data Entry LSB = value
      SND 0XB0 0X06 0X00 # Clear MSB
      BLOCK
    END
  END
END

To make things even easier, I exported my scene from MIDIFire. Now for Step 1. just install MIDIFire, then save and open this scene file on your device.

https://drive.google.com/drive/folders/1QpvsknLmaGFMMBeZLvgn6NRvskOE_mAQ?usp=drive_link

(You’ll still have to do steps 2 and 3 above)

1 Like

Can I just set up a Midi pedal (say 4 switches) direct usb to the CQ18, and then use that like the soft switches? I had something like this on my Behringer X-air. So MIDI control but no computer in the middle.

No you need something in between, like a PC, an ipad or a USB host device.

In theory, if your foot controller supported NRPN you might be able to do this using custom messages, but I haven’t tested it.

This is what I got from ChatGPT.

Very few MIDI foot controllers support sending NRPN messages directly without a host, but there are a few that can, either natively or through some creative setup. Here are the best options:


:white_check_mark: 1. Nektar Pacer

  • NRPN support: :white_check_mark: Yes – can send full NRPN sequences directly
  • Standalone: :white_check_mark: Fully standalone (5-pin MIDI out)
  • How: You can define custom MIDI messages, including multi-byte NRPN messages (MSB/LSB + Data Entry MSB/LSB)
  • Use Case: Excellent for controlling guitar processors (like Kemper), synths, or MIDI pedals
  • Note: Programming NRPN requires building the message step-by-step (4–5 commands per NRPN)

:warning: 2. RJM Music Mastermind GT/ LT series

  • NRPN support: :warning: Only via complex scripting or with external conversion (e.g., BomeBox)
  • Standalone: :white_check_mark: Yes
  • Note: These are very powerful, but better suited to Program Changes and CCs; direct NRPN is not a built-in focus

:white_check_mark: 3. Morningstar MC6 Pro / MC8 / MC10

  • NRPN support: :white_check_mark: Yes – supports sending raw MIDI messages
  • Standalone: :white_check_mark: Yes, with DIN MIDI or USB host (can power over USB battery)
  • How: You can define raw MIDI messages that make up an NRPN sequence (CC99, CC98, CC6, etc.)
  • Bonus: Has a Web GUI to program and preview NRPN messages
  • Use Case: Ideal for controlling devices like Eventide H9, Meris, or other MIDI-enabled pedals

:warning: 4. Behringer FCB1010 (with UnO firmware)

  • NRPN support: :warning: No native NRPN, but…
  • With UnO firmware or MIDI Solutions box: Can be made to send NRPN indirectly
  • Standalone: :white_check_mark: Yes
  • Note: Bit dated, programming is awkward, but still usable for basic MIDI

:wrench: Alternative Workaround:

If your foot controller can send multiple CCs per button press (e.g., CC#98, 99, 6, 38), you can manually build NRPNs. This is how NRPN works:

Basic NRPN Message (14-bit):

  1. CC#99 = NRPN MSB
  2. CC#98 = NRPN LSB
  3. CC#6 = Data MSB (value)
  4. CC#38 = Data LSB (optional)

:counterclockwise_arrows_button: Summary of NRPN-Capable MIDI Foot Controllers:

Controller Standalone NRPN Support Notes
Nektar Pacer :white_check_mark: :white_check_mark: Native Most flexible NRPN foot controller
Morningstar MC6/8/10 :white_check_mark: :white_check_mark: via raw MIDI Very programmable
RJM Mastermind GT/LT :white_check_mark: :warning: Partial Mostly for Program Change
Behringer FCB1010 :white_check_mark: :warning: Only with mods Not recommended for NRPN unless modified

Keeping in mind, they wouldn’t just work out of the box - you would have to custom program the messages based on the A&H MIDI protocols here: https://www.allen-heath.com/content/uploads/2024/10/CQ_MIDI_Protocol_V1_2_0_iss4.pdf.

I really doubt that any of these controller can directly connect to the CQ mixer.
The FCB1010 doesn’t even have any USB port…
Use AI with care…

I totally agree on the ‘use AI with care’ statement! It’s led me on many wild goose chases!

And yep, no chance if the controller doesn’t have USB (without something in between).

I have a Nektar Pacer and I’m pretty sure I could get it to work by sending a sequence of CC messages, but no way of knowing for sure without actually trying it.

Midi footswitch controller are midi device, not midi host.
Midi messages need a connection between 2 devices and you need to define a midi IN and a midi OUT.
In other words, if any pedalboard is connected directly to the USB-B of a CQ, you would need to select the CQ as a midi client from a pedal board.
I actually know no midi pedalboard that can do that.
You need a midi HOST for that, should it be a PC, or a dedicated box.

Ahh yes, after looking at it some more I think you’re dead right. You do need a midi host and controllers don’t have this.

Thanks for cleaning that up. There’s no substitute for real world experience! :wink:

To be honest I might be wrong, maybe that pedalboard exist.

I started to test Loopy Pro but have random crashes and Loopy sometimes is unable to reconnect to the CQ.
Do you have similar experiences ?

Never. Mine has been rock solid since day 1.

Is it Loopy that is crashing? Maybe it’s the hardware you’re running it on (if it’s an older phone)?

Or maybe there’s a bug in the software.. You could try using the latest beta on Test Flight and see if that helps.

I have disabled Siri and it is better now.
I have also allowed loppy to run in the background (when minimized).
No more issue so far.
Still have 6 days to test it.
But indeed, when its working it is rock solid.

1 Like