Juce VST3 plugin - MIDI SYS EX output issue

Hi this is my first topic on a forum, please excuse any bloomers

The problem is when I use MidiMessage::createSysExMessage() to send a SYS EX message, nothing is sent
If it try MIDI output using MidiMessage::noteOn() it works fine !
I have debugged into the code and can see the createSysExMessage constructs the SYS_EX packet Ok

the SYS EX MIDI output using MidiMessage::MidiMessage() was previously working but mysteriously stopped some weeks ago when I was not looking ! (several weeks ago I updated from 3.1.1 to Juce 3.2.0 but I cannot tell if this had any relation to when the fault occurred.)

1) can you spot what I am doing wrong ?

2) can you point me to an example of MIDI sysex output ?

3) I would prefer to use MidiMessage::MidiMessage() to send raw MIDI data (which was previously working)

I have been trying to get this going for 4 days now and it's starting to drive me potty
Please can you help me.

I have written in C for several years and wrote my first MIDI sequencer in 1983
but this is my first C++ project and I am using the excellent Juce framework 3.2.0 for the first time

My PC AMD w 16Gb RAM, I am using savihost3x64_1v42 http://www.hermannseib.com/english/savihost.htm to host my VST3 x64 plugin
It is receiving MIDI commands from the USB device and The Juce keyboard works Ok outputting notes to my USB MIDI device


//-----------------------------------------------------------------
// This is served every Audio block (few 100 us) for PlugInProcessor

void GgPuAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
  const int numSamples = buffer.getNumSamples();
  keyboardState.processNextMidiBuffer (midiMessages, 0, numSamples, true);
 
  processGuitarMidiBuffer(midiMessages);         // Pass any incoming midi messages to Guitar neck display & Replace MIDI Output messages
}
//---------------------------------------------------------------------------
void processGuitarMidiBuffer (MidiBuffer& midiMessages)
{
  MidiMessage midiMess;
 
  MidiBuffer::Iterator iIter (midiMessages);
  MidiBuffer processedMidi;
  MidiMessage message (0xf4, 0.0); // I do not know why this is req'd
  int time = 0;
  //------------------------------------------------
  // MIDI Input
  while (iIter.getNextEvent (message, time))
  {
    processMidiRxEvent (message, time);       // Service all MIDI Rx Input events
  }
  //--------------------------------------------------------------------------------------
  // MIDI Outut - message to test MIDI output SYS EX send
 
  byte *pMessTest;
  pMessTest = new byte[16];           // test buffer
  *(pMessTest + 0) = MIDI_SYS_EX;     // 0xF0 (will be prepended by createSysExMessage)
  *(pMessTest + 1) = 0x1A;
  *(pMessTest + 2) = 0x2A;
  *(pMessTest + 5) = MIDI_SYS_EX_END; // 0x7F (will be appended by createSysExMessage)
// Referenced by MidiEventList::toMidiBuffer().
//-----------------------------------------
// The data passed to createSysExMessage() in is wrapped with header and tail bytes of 0xf0 and 0xf7. OK
// midiMess = MidiMessage::MidiMessage(pMessTest, 4, 0.0f);     // This test does not send any MIDI message
  midiMess = MidiMessage::createSysExMessage(pMessTest + 1, 2); // This test does not send any MIDI message
//-----------------------------------------
// midiMess = MidiMessage::noteOn(5, 127, 1.0f); // this sends MIDI message OK to host
//-----------------------------------------
  processedMidi.addEvent (midiMess, time); 
}
//---------------------------------------------------------------------------

 

Hello,

​You add an event to the function local variable processedMidi, but you don't use it anywhere.

Hope this helps!

Also, all that code creating that array should be written like this:

const char data[] = { 0x1a, 0x2a };
midiMess = MidiMessage::createSysExMessage (data, numElementsInArray (data));

The function already adds the sysex header + footer bytes for you, and it looks like you're creating and leaking a heap array for no reason, as well as leaving bits of it uninitialised. If you're unfamiliar with how C++ heap/stack variables work, you'd probably benefit from spending some time learning about that.

 

Thanks for the response,  the code I submitted was a test, my real code did clean the heap and swap the MIDI out buffers 

So I have simplified it, I hope this makes more sense.


The code here does not send any MIDI output as it should do, can you explain ?
 

//------------------------------------------------
// This is served every Audio block (few 100 us) for PlugInProcessor
void GgPuAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
  const int numSamples = buffer.getNumSamples();
  keyboardState.processNextMidiBuffer (midiMessages, 0, numSamples, true);
 
  processGuitarMidiBuffer(midiMessages);
}
//------------------------------------------------
void processGuitarMidiBuffer (MidiBuffer& midiMessages)
{
  MidiMessage midiMess;
 
  MidiBuffer::Iterator iIter (midiMessages);
  MidiBuffer processedMidi;
  MidiMessage message (0xf4, 0.0);
  int time = 0;
  //------------------------------------------------
  // MIDI Input
  while (iIter.getNextEvent (message, time))
  {
    processMidiRxEvent (message, time); // Service all MIDI Rx = OK
  }
  //------------------------------------------------
  // MIDI Output
 
  const char data[] = { 0x1a, 0x2a };  // TEST SYS EX data
  midiMess = MidiMessage::createSysExMessage (data, numElementsInArray (data));
  processedMidi.addEvent (midiMess, time); 
  midiMessages.swapWith (processedMidi);
}
//------------------------------------------------

That looks OK, but looking at the VST3 code, sysex does seem to be implemented as far as I can tell, and we're not aware of problems with it.

I'm OOTO today but you might want to debug into the MidiEventList::toEventList() function to see if your data gets as far as being sent?

Hi Jules

Thanks for respondin so quickly

I debug into MidiEventList::toEventList() and midiBuffer has correct SYS EX data ie F0, 1A, 2A, F7

msg.isSysEx() - OK

e.type = 2

e.data.bytes = 0x1A

e.data.size = 2

e.data type = 0

e.sampleOffset = 0

I think this is as expected, but I put a break in the USB MIDI device, no SYS_EX is received

When I change the line:

 midiMess = createSysExMessage(.....) to  midiMess = MidiMessage::noteOn(5, 127, 1.0f); then it sends a note as expected

also when I presss a key on your piano keybaord that is sent Ok

 

TBH it sounds like it's your host that's not sending the message onwards.


Ha .... Yes it looks like my debug VST Host is only sending MIDI Note info, will update when I have found the root cause.........
 

createSysExMessage() x64 is broken, x32 is OK

I am now using Reaper 5.0.1  as a VST host  (I was using savihost3x64 as VST host)

So this is not my VST host problem, as when I compile using the introJucer x32 option, the MIDI sys ex works OK, my test is F0, 1A, 2A, 3A, 4A, 7F

When I change introJucer to x64, createSysExMessage () sends rubbish ie. 0xDD, 7B, 00, DD, 00, DD, 00 (all the rest of my VST works fine including MIDI Note send)

I have tries various other MidiMessage:: events

Working Ok in x64 = noteOn, aftertouchChange

Not working in x64 = controllerEvent, channelPressureChange, createSysExMessage, MidiMessage

None of juce's sysex handling is 32- or 64-bit specific, I'd suspect it's either your host that's behaving differently, or maybe your own code is messing up memory in a way that just happens to survive by sheer luck in 32 bit mode.