Getting a MidiClip to play

I’m stuck on something really simple with Tracktion: getting the engine to play a MidiClip. I’m working within the EngineInPlugin demo, and I know it’s working, because when I connect my Midi controller, I can hear sound. The demo has its own 4osc plugin loaded to receive Midi messages, but when I schedule my own on a clip, I get silence.

I’ve added a MidiClip like this:

    edit.ensureNumberOfAudioTracks(1);
  
    auto firstTrack = tracktion_engine::getAudioTracks(edit)[0];

    if (dynamic_cast<tracktion_engine::MidiClip*> (firstTrack->getClips()[0]) == nullptr)
        firstTrack->insertNewClip(tracktion_engine::TrackItem::Type::midi, { 0, 9999 }, nullptr);

    return *dynamic_cast<tracktion_engine::MidiClip*> (firstTrack->getClips()[0]);

Then I’ve added a bunch of notes to it like this:

    for (int i = 0; i < 100; ++i)
    {
        myClip.getSequence().addNote(55, i, 0.5, 1.0, 0, nullptr);
    }

What else do I have to do to get it to work? Again, I know that the engine is working, because it’s playing my Midi controller just fine. So it must be that the midi messages aren’t being routed from the MidiClip to the engine. How do I do that?

Sorry for how dumb this question is… I’m still finding it difficult to navigate Tracktion.

At a quick glance that looks like it should work. Are you sure you’re playing back the transport from the start?

Ah, I’d forgotten that! I’ve got it working in the demo now. There must be another problem in my application, because the transport is already playing there, but at least now I know what I’m working with. Thanks Dave!

@dave96 I’m still having problems, but I can formulate the question better now. I have two clips–one on track 1, and one on track 2. The first one is playing, but not the second. So my constructor looks like this:

EngineInPluginDemo()
    : AudioProcessor (BusesProperties().withInput  ("Input",  AudioChannelSet::stereo())
                                       .withOutput ("Output", AudioChannelSet::stereo())),
    audioInterface (engine.getDeviceManager().getHostedAudioDeviceInterface()),
    clipOnFirstTrack(getOrCreateFirstMidiClipOnTrack(0)),
    clipOnSecondTrack(getOrCreateFirstMidiClipOnTrack(1))
{
    audioInterface.initialise ({});
    
    setupInputs();
    create4OSCPlugin();

    for (int i = 0; i < 100; ++i)
    {
        clipOnFirstTrack.getSequence().addNote(55, i, 0.5, 127, 0, nullptr);

        clipOnSecondTrack.getSequence().addNote(66, i + 0.5, 0.5, 127, 0, nullptr);
    }

    auto& transport = edit.getTransport();

    transport.position = 0.0;

    transport.play(true);
}

I can hear note 55 from the first track, but not note 66 from the second track. I’m guessing that the edit or the transport doesn’t about track 2. What can I do to load track 2 correctly?

Here is where I create the tracks:

tracktion_engine::MidiClip& getOrCreateFirstMidiClipOnTrack(const int i)
{
    edit.ensureNumberOfAudioTracks(i + 1);
  
    auto firstTrack = tracktion_engine::getAudioTracks(edit)[i];

    if (dynamic_cast<tracktion_engine::MidiClip*> (firstTrack->getClips()[0]) == nullptr)
        firstTrack->insertNewClip(tracktion_engine::TrackItem::Type::midi, { 0, tracktion_engine::Edit::maximumLength - 1 }, nullptr);

    return *dynamic_cast<tracktion_engine::MidiClip*> (firstTrack->getClips()[0]);
}

Just a real quick guess but I think create4OSCPlugin() is only creating an instance of 4OSC on track 1.

Again you are right about my error, but I’m still getting silence. One track is working, but not the other.

Could it be something to do with HostedAudioDeviceInterface? I’m using this in the parent class to interface between the AudioProcessor and the Engine class. I’m just running engine.getDeviceManager().getHostedAudioDeviceInterface().initialise({}) on it for setup. Does HostedAudioDeviceInterface need to be told about both of the tracks?

Just to clarify something: I actually want to route the MidiClip to the default Midi output (Windows GS synth), not to the 4OSC plugin. Because the Windows GS synth works when I plug in my Midi hardware, I’ve been assuming that the MidiClip would automatically be routed there. But maybe I have to do something to the track or to the clip to tell it to use the default Midi output?

You can’t send data to a MIDI output from inside a plugin, you’d need to route the MIDI out to the host and then let the host do with that what it likes. MIDI output from a plugin is the one thing we have left to do for plugin support at the moment though so you won’t be able to do this just yet.

You shouldn’t need to change anything in the HostedAudioDeviceInterface , just make sure you have an instance of 4OSC on the second track and it should be output as audio on channels 1-2 of the plugin, the same as track 1.

Ah, I see. Glad I asked otherwise I would have been going round in circles for hours! I’ll put a dummy 4OSC in for testing purposes, and then await the update. Will there be an update on this forum when it’s complete?

Also, am I going to have problems with this when it comes to VST3? I’ve read the other threads about the horrors people have with VST3 and Midi, but I was hoping that I’d get away with doing simple things like sending midi messages out…

To be honest I’m not completely sure.
I think you can send notes but not CC messages out of VST3 plugins.