A midi effect that takes midi data and produces MPE data

Howdy all. After working through some tutorials, I’m giving my first project a shot. My JUCE (and C++) knowledge is pretty limited though, so please forgive any blatant misunderstandings on my part. (There are probably many.)

My goal:
To create a plugin that remaps midi data received from a controller to MPE data.

The input midi data is really just arbitrary controller information (the key I’m hitting on this device: http://www.c-thru-music.com/cgi/?page=spec_49-selfless), which I use to determine the pitch of the note I actually want to be sounded. I need to use MPE because the output will be microtonal.

(I’m actually doing a little more than that: depending on some user selections, the midi will either be converted to MPE midi, or to a DynamicTonality specific scheme for mapping midi notes and channels to “period and generator coordinates”. http://dynamictonality.com/about.htm But that’s relatively straightforward. It’s the MPE part I’m not sure about.)

What I’ve done so far:
I’ve followed along with this video from the Audio Programmer on YouTube with Eyal Amir:


And it seems like a good template for what I’m trying to do. I’ve also walked myself through the 2 MPE tutorials here:
https://juce.com/learn/tutorials

Those tutorials seem focussed on receiving MPE data that has already been generated (by a hardware device) though, and that’s where I’m realizing I don’t have a clue what to do.

So…

In the Midi Effect video, the midi buffer is passed by reference into a process method. Each midi message in the buffer is iterated over, being modified somehow, passed into a new buffer, and then the original buffer is replaced by the new one.

But if I want to use MPE for the output… I assume need to create an MPEInstrument to keep track of all the MPE things, like currently used channels, right? If so, is the above method (Input midi buffer --> iterate --> replace) still viable? Am I able to just give the MPEInstrument the information about the notes I want to play, and ask it for the appropriate midiMessage to be put into the new buffer? If so, how would I go about doing that? It doesn’t look like the MPEInstrument class has functions for something like “addNoteAndReturnCorrespondingMidiMessage” and, given that that’s the case, I’m guessing I’m fundamentally misunderstanding how the class might be used in this situation, or whether it should be used at all.

Thanks for any help here. At least to show I value people’s time and expertise, I’d be happy to tip a couple dollars worth of Bitcoin Cash (BCH) to whoever can help me sort this out.

Thanks again!

I’m also interested in this, even tho I haven’t digged yet into MPE as I’m actually working on other parts.

But as a little aid, take a look at MPEMessages from the documentation, specially this part:

This helper class contains the necessary helper functions to generate MIDI messages that are exclusive to MPE, such as defining the upper and lower MPE zones and setting per-note and master pitchbend ranges.

You can then send them to your MPE device using MidiOutput::sendBlockOfMessagesNow.

All other MPE messages like per-note pitchbend, pressure, and third dimension, are ordinary MIDI messages that should be created using the MidiMessage class instead. You just need to take care to send them to the appropriate per-note MIDI channel.

Btw no need to tip anyone. Except Jules and other Juce devs, we all have been newcommers and asked for help here (I still ask) :smile:

Howdy, thanks very much for the response!

All other MPE messages like per-note pitchbend, pressure, and third dimension, are ordinary MIDI messages that should be created using the MidiMessage class instead. You just need to take care to send them to the appropriate per-note MIDI channel.

I realize you may not know, but to anyone else following along: Does this mean that, if I want to generate outgoing MPE midi, I will need to create the messages manually? I assume an MPEInstrument would still be the best tool to keep track of what channels are currently being used?

Basically what I’m imagining now is just using the isUsingChannel() function to find the next currently available channel, creating the midiMessage manually using that channel and the pitch I want to sound (giving me the midi number and initial pitch bend value), then sending that midiMessage two places: out of the plugin (by replacing the buffer), and to the processNextMidiEvent() function so that the channel is taken up in the MPEInstrument, and I’ll know that that channel isn’t available for the next message.

My default assumption was that more of that process would be automated by the MPE relevant classes but, as I think about it more, I guess it wouldn’t be surprising to find out that they weren’t.

But I’m asking here just to be sure I’m not missing anything big. Thanks for any help as always!

Btw no need to tip anyone. Except Jules and other Juce devs, we all have been newcommers and asked for help here (I still ask) :smile:

Haha great to hear that the community here is so supportive. I do hope that someday casual tipping will be a norm in forums like these, because I think it will over-all lead to higher quality answers (maybe some folks will even be able to make a living by being helpful on the internet xD), but it’s great if people here help each other out regardless =)

Did you happen to find a good solution for this? I am working on a fairly similar project, and trying to figure out what to do. I’m thinking about messing around with the MPEChannelAssigner or extending MPEInstrument or MPESynthesiserBase, but if you’ve already found an answer, that would be super helpful.