Take DAW piano roll input, and generate output back into the DAW piano roll

I’m a newcomer in JUCE, and I’m developing a plugin for my engineering bachelor thesis at the university, with the aim of harmonizing a melody that a music producer introduces, through the piano roll of the host Reaper (All this launching a model of deep learning, which for what I want to consult in this post is irrelevant and I already have developed). Basically what I want to achieve and I do not know how, is introducing a melody in the Reaper piano roll, then this is processed (Task of the deep learning model) and draw the harmony that has been generated on the same piano roll (being drawn both the initial melody, as the harmony that is automatically generated on this).

I am using Ubuntu 20.04, JUCE 6, Reaper 6.18 and C++14.

The configuration of the JUCE project is the following:

The most that I have managed to understand so far, is that inside the AudioProcessor::processBlock() method, the MIDI inputs of the host are processed. Playing Reaper piano roll notes doesn’t work. The plugin consists of a button to generate the accompaniment, based on what is entered in the text field that appears just below it, and there is also a text field that is at the bottom of the plugin (see screenshots below):

As you can see in the mixer, there is audio input when I play some piano roll note.

The processBlock method code is as follows:

void HarmonizationmachineAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
juce::ScopedNoDenormals noDenormals;
auto totalNumInputChannels  = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();

// In case we have more outputs than inputs, this code clears any output
// channels that didn't contain input data, (because these aren't
// guaranteed to be empty - they may contain garbage).
// This is here to avoid people getting screaming feedback
// when they first compile a plugin, but obviously you don't need to keep
// this code if your algorithm always overwrites all the output channels.
for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
    buffer.clear (i, 0, buffer.getNumSamples());

// This is the place where you'd normally do the guts of your plugin's
// audio processing...
// Make sure to reset the state if your inner loop is processing
// the samples and the outer loop is handling the channels.
// Alternatively, you can process the samples with the channels
// interleaved by keeping the same state.
for (int channel = 0; channel < totalNumInputChannels; ++channel)                                                                                                                                                  
{
    auto* channelData = buffer.getWritePointer (channel);
}

int var = (int)midiMessages.isEmpty();
auto var2 = juce::String(var);
dynamic_cast<HarmonizationmachineAudioProcessorEditor*>(getActiveEditor())->midiOutput.setText(var2, true);
}

It does not work either introducing a melody by hand in the piano roll, nor playing the corresponding track.

I have also tried to find information in this forum about similar problems that other people may have had and nothing worked.

I have tried to iterate on the MidiBuffer as explained in the MidiBufferIterator docs, and then display the information in the editor from the AudioProcessor class as explained in this page (Showing the result of the MidiBuffer::IsEmpty() function, and always returns the value 1, that is, empty MidiBuffer). I have to mention that showing things like that is temporary, in order to debug it somehow. Everything I need to show, I show it in a text field, which is the one at the bottom of the plugin (You can see it in the previous screenshot).

I don’t know exactly if what is received from the piano roll are MIDI events, or if directly everything appears in the buffer, or if it is even none of this and it is something I am not understanding. I think there are basic concepts I am not understanding, and for that reason I cannot advance. As I don’t know those concepts, I don’t know the real scope of this that I want to do either, not even if it’s possible.

I am grateful for all type of help.

Greetings.

I’m not exactly sure I understand what you want to do. But if you want to make a plugin that writes midi notes into the piano roll of the DAW, then you haven’t fully understood how midi plugins work. When you get the buffer, you cannot send it back to midi input. That would be the wrong direction. You can only record the midi data you generate if you do that in Reaper. To do this, you need to add another track and route the output of one track to the input of the other. But that’s probably not what you want.

I understand what you are saying, and you solve my lack of understanding.

What do you mean here is basically creating another track with both, the initial melody and the harmonization, for example, below the track of the initial melody, right? And how could I do that exactly? Could I title the generated track?

I still don’t understand something that I wasn’t doing correctly, would putting a note on the piano roll be processed within the processBlock method? In that case, how exactly would I have to iterate on the MidiBuffer?

Thank you very much for responding quickly.