I cannot figure out how to configure Midi Input for tracks in project I’m working on.
I have te::VirtualMidiInputDevice on te::AudioTrack A ("Drum 1 Input"on screenshot) and Arrpegiator plugin on same track.
I would like to use te::AudioTrack B (“Drum 1” on screenshot) as destination for Midi data sent from te::AudioTrack A, so it get’s recorded into te::MidiClip on te::AudioTrack B (“Drum 1” on screenshot).
I tried setting te::AudioTrack output and it seem to affect only audio, not Midi
trackA ->getOutput().setOutputToTrack(trackB)
Also tried:
if (auto* virMidi = dynamic_cast<te::VirtualMidiInputDevice*>(&track->getMidiInputDevice())){
virMidi->setEnabled(true);
if(auto instance = edit.getCurrentInstanceForInputDevice(virMidi)){ // and track->getMidiInputDevice() as argument as well
instance->setRecordingEnabled(*track, true);
}
}
But I’m not getting any instances for this InputDevice
Screenshot from Waveform shows exactly was I want to achieve “Drum 1 Input” track as MidiTrack Input for “Drum 1” and be able to record all generated Midi from Arpeggiator.
This is where the myriad of routing options becomes confusing
setOutputToTrack sets the “Track Destination” property in Waveform which send the track’s output to the start of the plugin chain of the destination track.
I think what you’re after is using "Drum Input 1"s WaveInputDevice as an input to track “Drum 1”.
This should be achievable with the following:
InputDevice& id = sourceTrack->getWaveInputDevice();
// Make the track's InputDeviceInstance visible to the EditPlaybackContext
edit.getEditInputDevices().getInstanceStateForInputDevice (id);
if (auto epc = edit.getCurrentPlaybackContext())
if (auto sourceTrackInputDeviceInstance = epc->getInputFor (&id))
sourceTrackInputDeviceInstance->setTargetTrack (destTrack, inputSlotIndex, moveToTrack);
I’m only receiving Midi Events on “Destination track” if I use inputTrack->“getMidiInputDevice()” instead of “getWaveInputDevice()”, but Midi Messages are original from te::VirtualMidiInputDevice, not modified by my Arpeggiator.
I modified MidiRecording Example to demonstrate issue. Added function with all setup I’m doing.
Sorry, the audio/midi device was my mistake, as you say it should be the MIDI device if you want MIDI message
There’s a few problems with your code though, I’m not sure if they are the source of the problem though (I’ve also added some spacing to make it a bit more readable):
for (const auto instance : edit->getAllInputDevices())
{
DBG(instance->getInputDevice().getName());
if (instance->getInputDevice().getDeviceType() == te::InputDevice::virtualMidiDevice
&& instance->getInputDevice().getName() == virtualDeviceName)
{
if (auto inputTrack = EngineHelpers::getOrInsertAudioTrackAt(*edit, 0))
{
instance->setTargetTrack(*inputTrack, 0, true);
instance->isLivePlayEnabled(*inputTrack); //!!! This call doesn't make any sense, it's a const method that returns a bool so won't actually do anything...
inputTrack->setName("InputTrack");
if (auto destTrack = EngineHelpers::getOrInsertAudioTrackAt(*edit, 1))
{
destTrack->setName("DestTrack");
//Setup MidiTrackInput
te::InputDevice& id = inputTrack->getMidiInputDevice();
// Make the track's InputDeviceInstance visible to the EditPlaybackContext
edit->getEditInputDevices().getInstanceStateForInputDevice (id);
if (auto epc = edit->getCurrentPlaybackContext())
{
if (auto sourceTrackInputDeviceInstance = epc->getInputFor (&id))
{
sourceTrackInputDeviceInstance->setRecordingEnabled (*destTrack, true);
sourceTrackInputDeviceInstance->setTargetTrack (*destTrack, 0, true); //!!! This probably needs to go above the setRecordingEnabled call or the setRecordingEnabled will fail as it hasn't been assigned to the track yet
sourceTrackInputDeviceInstance->isLivePlayEnabled(*destTrack); //!!! As above: This call doesn't make any sense, it's a const method that returns a bool so won't actually do anything...
}
}
}
}
virtualMidi = dynamic_cast<te::VirtualMidiInputDevice * >(&instance->getInputDevice());
}
}
With those changes, does it work as expected?
If not, have you stepped through that method to check all your ifs are actually being entered?
Thanks for fast reply and sorry for formatting. I usually use CLion and it takes care of it, unlike xCode, which I’ve used for modifying my example.
I updated my code after your remarks. But it still doesn’t work as expected. I don’t see any midi or audio passed “inputTrack” -> “destTrack”.
te::InputDeviceInstance* state looks correct though.
Woohoo! Looks like code above gets me to result I want. I actually had to add Arpeggiator plugin to inputTrack, once it was added it generates and sends Midi to destTrack.
For scenarios where I don’t have Midi Plugin (arpeggiator plugin in my case) on inputTrack, but still want to route Midi to destTrack, I used function below which routed output to destTrack.