Generating MIDI data for use in DAWs

Hi there. I’m very new to JUCE (and still getting used to C++), so any advice would be greatly appreciated. I would like to build a JUCE audio plug-in that generates MIDI data to be read by a DAW (like Logic or Ableton). I want my DAW to pick up the MIDI just like it would from a USB MIDI keyboard, except the data is generated by my tool.

To start with something simple, I have tried the following so far:

  • created a new audio plugin in the projucer
  • In PluginProcessor.cpp, in the Processblock, added
    auto message = MidiMessage::noteOn (1, 5, (uint8) 100);
    MidiBuffer midiBuffer;
    midiBuffer.addEvent(message, 0);
  • As an alternative, I also tried
    MidiMessage message = MidiMessage::noteOn (1, 5, (uint8) 100);
    midiMessages.addEvent (message, 0);

I tried compiling each version, then opened Logic and put the plug-in onto an audio track. I then opened a MIDI instrument track, hoping that it might pick up the MIDI. It doesn’t. What am I doing wrong here?

Have you enabled Plugin MIDI Output under Plugin Characteristics in the Projucer?

Yes, I have! So that’s unfortunately not it. Thanks though.

Works for VST3 versions, for AU I guess you have to set the AU Main Type to kAudioUnitType_MIDIProcessor

Still no luck I’m afraid. Do you think this could be related to me updating my Mac recently? Or maybe something’s wrong with my global paths?

It’s not a path issue if the plugin builds and is seen by the host.

Some hosts have poor support for plugins that generate MIDI output and it can be tricky to coax the host to allow those to run properly.

Did you insert your plug-in as a midi effect before your synth or after as an audio effect? I just tested both VST3 in Reaper and AU in Logic, and it works like a charm. In Logic I had to hit play for the plug-in to produce MIDI

Thank you both for your help, appreciate your time. @danielrudrich I tried both those things, I compiled my plugin both as a MIDI effect and normal plugin and neither seems to work… Would it perhaps be possible for me to send you some of my work to see if it differs from yours, or for you to send me yours? I even tried to hit record to see if it would pick something up in a MIDI recording.

45 04

The three setups I tried.
I compiled as MIDI effect and normal audio plug in and tried all possible combinations for each (as shown in the pictures).

That’s what I did:

  • new audioplugin project
  • formats: VST3, AU
  • characteristics: Plugin MIDI Output
  • AU Main Type: kAudioUnitType_MIDIProcessor
  • PluginProcessor.cpp end of processBlock:
MidiMessage message = MidiMessage::noteOn (1, 5, (uint8) 100);
    midiMessages.addEvent (message, 0);

(there’s no corresponding note off event, but should do the job for testing)

  • compiled it, and tested it in Reaper (normal audio effect), and logic into the MIDI effect section into some synth

Thanks, I started again from scratch but still no luck. This is very strange. My audio output works and I am receiving MIDI from all channels as expected. Normal keyboard MIDI input works, too. BTW when you say end of process block, do you mean inside of or after the bit saying

for (int channel = 0; channel < totalNumInputChannels; ++channel){…}

?
I tried both anyway, so it isn’t that.

I can’t upload files as I’m new but I’m uploading my compiled plug-in to Dropbox in case it helps:

Ohh, it works for the Logic Retro Synth!! I have been trying the Vintage Electric Piano, which for some reason doesn’t like it. Do you have an idea why this could be? I thought all software instruments would pick up MIDI in the same way. Is it a channel thing? Though can’t be since I ticked “all”…

Some more intel: no matter how I set my synth amp ADSR, the note has an endless sustain. I know there is no note off but unless I have a sustain, it should still end I thought. Lots of riddles here!

Just playing with it some more. It appears to keep re-triggering the sound in regular intervals. Got some accidental dubstep from another synth :wink:

You should also send a note off in order to stop the sounds, otherwise you have a long decay :slight_smile:

Isn’t accidental what defines dubstep? :wink:

haha I guess so!

I agree, though it sounds to me as though the note keeps getting triggered, that’s why I get a wobble. It’s not a long sustain; and it also happens on short, percussive synth presets. Will look at it some more tomorrow. Thanks for all your help so far!

Hi again. So as suspected, the MIDI off message does not work as expected.

Currently, it says the following at the end of my process block:
midiMessages.addEvent(MidiMessage(MidiMessage::noteOn(1,(int)(60),(uint8) 100)),0);
midiMessages.addEvent(MidiMessage(MidiMessage::noteOff(1,(int)(60),(uint8) 100)),100);

When testing this Logic, the note seems to get started over and over again and never ends. Does anyone know why this might be?

Since processBlock is repeatedly called while the audio is running, if you don’t have any condition to limit the notes from being added, they just keep on being added. And because the processing blocks may be quite short, you may get some weird effects from synths following your MIDI generator plugin because they are quickly hammered with incoming MIDI notes.

The note-offs not working may be related to that, synths might not expect to get a note-off during the same processing block for the same note. You somehow have to keep track of when the note ons and note offs should happen and then accordingly add the messages to the MIDI buffer.

Ahh, that makes sense. Goes to show how new I am to the whole thing. Thanks, will see if I can figure it out.

Thanks again for everybody’s help so far. I’m stuck on the next step now.
I am struggling to work out how the process block works in regards to musical timing. I read many forum entries and the documentation but I’m still struggling and feel that I need to ask some dumb questions for now.
Say I wanted to use a toggle button to control an endless sequence of MIDI notes (of random pitches but equal durations) being turned on and off. When I turn the button on, the sequence starts; and when I turn the button off, the sequence stops. I’m using the following code at the moment. IsOn is a boole that’s initiated as false above the process block and IsPlaying is my button toggle info.

if ((IsOn == true)&&(IsPlaying == false))
{
IsPlaying = true;
auto rand = Random::getSystemRandom().nextInt (Range (21, 109));
midiMessages.addEvent(MidiMessage(MidiMessage::noteOn(1,(int)(rand),(uint8) 100)),1);
midiMessages.addEvent(MidiMessage(MidiMessage::noteOff(1,(int)(rand),(uint8) 100)),80000);
IsPlaying = false;
};

I understand that the process block is continuously being recalled, but I don’t understand why the next note plays before the previous note has stopped, since I’m only setting IsPlaying back to false afterwards.

Presumably I am using this completely wrong. Can somebody help suggest the tools I need to make the timing work? Thanks!

You are still not counting the elapsed times for the notes in any way. The time stamp given to addEvent should be a time stamp within the current processing buffer. If you put something like 80000 there for the note off message, the event is likely just ignored by Juce or the host. And it doesn’t mean the next processBlock call is going to happen after 80000 samples. The processBlock calls happen at some relatively short time period, typically something like 64 to 1024 samples. That is completely independent of what you put into the MIDI messages.

You will need to figure out which MIDI messages and when to put into the current MIDI buffer : put a note on message into the messages at the first processBlock call, then you don’t maybe add any messages during lots of the processBlock calls, and finally when the note should end, you add the note off event and possibly a new note on event for the next note and so on. The logic needed to implement that is tricky because you need to keep track of what notes are currently playing and so on. You can look at the ArpeggiatorPluginDemo.h in the Juce examples to get some ideas how to implement it.