Record injected MIDI messages


Is it possible to emulate MIDI input and have it recorded to clips?

AFAICT, AudioTrack::injectLiveMidiMessage plays back the MIDI data but doesn’t record it.

If you use DeviceManager::createVirtualMidiDevice to create a virtual MIDI device, you can send messages to it and record them just like you would with a PhysicalMidiDevice.


From reading this thread:

I got the impression that this is not the purpose of Virtual MIDI Device?! Specifically:

I mistakenly assumed that the VirtualMidiInputDevice class would allow me to pass midiMessages that I generate myself to a track, as opposed to a physical device.

That is exactly what I want to do!

I’m sorry if it’s just me being confused but don’t these answers seem to contradict one another?

Is there any example of VirtualMidiInputDevice being created and used in this fashion?

No, sorry we don’t have an example of this as it’s a bit of a niche use case.

I think this post is the best example:

That topic is a bit confusing as it switches between exposing ports to the OS and creating “virtual” devices inside the engine. If you want to do the latter, VirtualMidiInputDevice is probably the best way to go and send MIDI messages to it as above.

Be careful using getDefaultMidiInDevice, there is likely to already be a default MIDI device so you might want to improve the logic here. It all depends if you’re loading saved settings with a virtual MIDI input already created etc.

Thank you!

That clarifies things – I’ll try createVirtualMidiDevice!

I’m sorry but I can’t make it work…

engine.getDeviceManager().createVirtualMidiDevice ("Virtual");
for (auto mi : engine.getDeviceManager().midiInputs) {
    if (mi->getDeviceType() == te::MidiInputDevice::virtualMidiDevice) {
        virtualMidiInput = mi;

// ... and later ...

virtualMidiInput->handleIncomingMidiMessage(nullptr, mm);

But nothing is played back and nothing is recorded. I suspect that the problem is that I need to choose the virtual MIDI input as the input for an audio track – could that be correct? I don’t understand how to do that; the examples use InputDeviceInstance::setTargetTrack but in this case I don’t have an InputDeviceInstance.

(Does the fact that createVirtualMidiDevice doesn’t return the new device perhaps suggests that I’m not supposed to use it in this way at all?)

Yes, you’ll need to assign an instance to a track for it to have any effect:
EditPlaybackContext::getInputFor (virtualMidiInput)->setTargetTrack (track, 0, true)

Many thanks, now I got it working!

Although I still don’t understand how to connect the physical midi inputs to the virtual MIDI device – because that is what I have to do, right? I basically want to route all (enabled) physical MIDI inputs plus my additional generated MIDI events to a single track.

Also: if there are multiple tracks, do I need one virtual MIDI input per target track? Would it in this way be possible to route all incoming MIDI from all devices to multiple tracks?

If you add the name of a physical device to the VirtualMidiInputDevice::inputDevices array, any incoming messages on that device will also be sent to your virtual device.

You can route the same VirtualMidiInputDeviceInstance to multiple tracks (to get the same MIDI input on all tracks) by passing false as the last parameter here: EditPlaybackContext::getInputFor (virtualMidiInput)->setTargetTrack (track, 0, false).