MIDI CC Data

This is not strictly speaking a tracktion_engine question, but I thought those implementing tracktion_engine in their applications may be knowledgeable on this.

Now that I have MIDI CC editing capability in my DAW, I am noticing that MIDI CC data is somewhat messy. This caused me to think that I need to implement some filtering or cleanup for the CC data. But before I create something to clean the CC data, I am wondering.

Is this what most do? And is there, perhaps, some JUCE functionality in this regard that I have not discovered?

What do you mean by messy?

We have some functionality in the engine to “simplify” recorded MIDI to reduce the number of points.

There are a lot of duplicates, for example, at least in the case of sustain (type 64) CC data. And, it appears that a lot of the sustain “off” messages are missing.

So my plan was to run the CC data through some code to remove duplicates and add type 64 “off” data as needed.

If there is built-in functionality, it will be great to use that, if you can point me in the right direction?

Thank you!

And, also, is it possible to get the raw CC data?

It’s here: simplify (AutomationCurve&, **int** strength, EditTimeRange range);

You can’t get the raw CC data, it doesn’t make much sense after it’s been recorded because at the very least it needs a timestamp. Also because of multi-byte events we store them all as MidiControllerEvents. You can get the type and value from those though which are essentially all a CC has.

Thank you! I will check it out.

When I sat down to try this out, I noticed that the first parameter is an AutomationCurve&. Is this function intended for automation values, or is there a way to use it with MIDI CC events?

Oh sorry, I had a bit of a brain melt. That is to simplify automation, not CC data. I don’t think we have anything for that.

You could probably roll your own function based on AutomationCurve::simplify for CC data though.

No problem. Your help is always appreciated!

A side question—normally, midi values are 0 to 127, but I am seeing 0 to 16256, at least for sustain (type 64) values. Is there a story behind this?

I think they’re normalised to 14bits because pitch wheel has that resolution. It also guards us against future higher resolution export formats like MIDI 2.0.

If you look in tracktion_MidiList.cpp at addToSequence, you’ll see how the MidiControllerEvent gets converted to a juce::MidiMessage.

I’m wondering if someone having issue with midi cc. I’m setting cc events like this,

MainComponent::MainComponent()
{
    setSize (600, 400);
    
    edit = std::make_unique<tracktion_engine::Edit> (options);
    
    edit->ensureNumberOfAudioTracks (8);
    if (auto track = tracktion_engine::getAudioTracks (*edit)[0]) {
        const tracktion_engine::EditTimeRange editTimeRange (0, edit->tempoSequence.barsBeatsToTime ({ 2, 0.0 }));
        track->insertNewClip(tracktion_engine::TrackItem::Type::midi, "MidiClip", editTimeRange, nullptr);
        if (auto clip = dynamic_cast<tracktion_engine::MidiClip*> (track->getClips()[0]))
        {
            auto &dev = track->getOutput();
            auto &deviceManager = engine.getDeviceManager();
            
            dev.outputsToDevice(deviceManager.getDefaultWaveOutDevice()->getName(), true);
            dev.setOutputByName("Tracktion MIDI Device");
            
            auto &seq = clip->getSequence();
     
            seq.addControllerEvent(2.0f, 9, 54, nullptr);
            seq.addControllerEvent(4.0f, 9, 54, nullptr);
            seq.addControllerEvent(6.0f, 9, 54, nullptr);
            seq.addControllerEvent(8.0f, 9, 54, nullptr);
            seq.addControllerEvent(2.0f, 9, 54, nullptr);
            seq.addControllerEvent(4.0f, 9, 127, nullptr);
            seq.addControllerEvent(6.0f, 9, 127, nullptr);
            seq.addControllerEvent(8.0f, 9, 127, nullptr);
            seq.addControllerEvent(2.0f, 9, 127, nullptr);
            seq.addControllerEvent(4.0f, 9, 127, nullptr);
            seq.addControllerEvent(6.0f, 9, 127, nullptr);
            seq.addControllerEvent(8.0f, 9, 127, nullptr);
        }
    }
    
    auto &transport = edit->getTransport();
    transport.play(true);
    DBG(edit->state.toXmlString());
}

If I output it to external devices or apps I have 0 cc values always.

But in tree state values looks ok, what could be the issue? I’m doing this with latest develop branch

I think the value should be 0-16383.
All MIDI values are in this large range to support higher precision MIDI in the future and for messages that have higher precision like pitch bend.

If you just add << 7 to all your values (e.g. 54 << 7), do they come out as expected?

Oh yes, this solved the problem! Thank you!

Great. I agree this should be better documented or better still type-enforced.