In regards to the MIDI Output problem.
-
I've found out something that might be a bug and the root cause of why in some cases developers have problems with midi out events not being fired.
My Setup:
- Windows 10
- Cubase Pro 13
- Visual Studio 2022.
- HISE 3.6.2
Plugin Export Settings:
- Export As MIDI FX
Checked Flags:
- Enable MIDI Input FX
- Enable MIDI Out
- Enable Sound Generation FX
- VST3 Support
So after a day's worth of failed attempts to produce MIDI Out Events, I've built a debug version to see what's going on in the C++ code.
Here's what I've found...
When inserting an event to the artificalEvents buffer an assertion fails, because the buffer is full (256 events),
At HiseEventBuffer.h Line: 538
void HiseEventBuffer::addEvent(const HiseEvent& hiseEvent) { if (numUsed >= HISE_EVENT_BUFFER_SIZE) { // Buffer full.. jassertfalse; return; } //... }
In my case I've soon realized that these 256 where the initial sequence of the plugin, plus the first additional events I've inserted manually.
So, normaly the buffer should be cleared, upon rendering, and the events should have been purged. This should happen here:
At HiseEventBuffer.h Line: 756
while (HiseEvent* e = iter.getNextEventPointer()) { if (e->getTimeStamp() < highestTimestamp) { targetBuffer.addEvent(*e); numCopied++; } else { break; } }
However this loop exits immediatelly. That's because
highestTimestamp
ultimately gets its value from thenumSamplesThisBlock
defined in MainController.cpp.I'm assuming this number is set by the host. However in Cubase it is set to zero!!! So any event's timestamp is bigger than
highestTimestamp
and therefore no event is passed to the midi out, or is cleared from the queue. This explains both the absense of MIDI Out events, and the buffer assertion.So, I've managed to get the MIDI Out to play nicely, by changing the
numSamplesThisBlock
tooriginalBufferSize
for all midi buffer calls which gives the correct number of the buffer samples.At MainController.cpp Line: 1134
#elif HISE_MIDIFX_PLUGIN //-- synthChain->processHiseEventBuffer(masterEventBuffer, numSamplesThisBlock); synthChain->processHiseEventBuffer(masterEventBuffer, originalBufferSize); //++ midiMessages.clear(); HiseEventBuffer::Iterator it(synthChain->eventBuffer); while (auto e = it.getNextConstEventPointer(true, false)) { if (e->isTimerEvent()) continue; auto m = e->toMidiMesage(); midiMessages.addEvent(m, e->getTimeStamp()); } //-- processMidiOutBuffer(midiMessages, numSamplesThisBlock); processMidiOutBuffer(midiMessages, originalBufferSize); //++ #else //...
IMHO this has to do something with DSP optimization. For example the host thinks that there should not be any audio run through the FX, so it sets the number of samples to process to zero.
I'm guessing that different hosts calculate the number ending up in
buffer.getNumSamples()
differently and that's why in some setups midi out works, while it fails in others.I'm not that familiar either with HISE, JUCE or VST to form an "expert" opinion, but I think that's the root cause of the problem.
Hopefully I've helped somehow with this issue.
PS: Mr Hart, This is by far one of the most elegant and promising projects I've came across. You are a genius indeed :)