VstMidiEvent for the braindead: NumEvents question.

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

Currently I'm developing my own vst plugin and I can't get the idea about the maximum number of events that a host can send to a plugin in one block.
Is that somehow related to sampling rate, asio buffer size and the speed of midi(31250 bits per second)?

Post

There's no defined maximum (except for the obvious, which is 2147483647 8-) ...). And no, it isn't related to any of the sizes, since the MIDI speed doesn't have any meaning as long as the MIDI message doesn't leave the computer and travels on a real MIDI cable.

If I was you and would have to buffer the events, I'd allocate a ring buffer for 1000 messages and ignore any overflow. Chances are high that you won't ever see more than 20 messages per block, but 1000*sizeof(VstEvent) isn't really something to worry about these days.
"Until you spread your wings, you'll have no idea how far you can walk." Image

Post

Exactly. Think inside the box! ;)

Post

arakula wrote:If I was you and would have to buffer the events, I'd allocate a ring buffer for 1000 messages and ignore any overflow. Chances are high that you won't ever see more than 20 messages per block, but 1000*sizeof(VstEvent) isn't really something to worry about these days.
Note that different types of events have different sizes...

[2c]
Grtx, Marc Jacobi.
VST.NET | MIDI.NET

Post

Also bear in mind you don't usually need to copy the events sent from the host, the pointer to the host's events passed by processEvents() remains valid during process(). Rather than laboriously making a copy of the events, just copy the pointer...

long SeVst::processEvents (VstEvents* events)
{
m_events = events;
return 1; // want more
}

void SeVst::processReplacing(float **inputs, float **outputs, long sampleframes)
{
if( m_events )
{
for( int i = 0 ; i < m_events->numEvents ; i++ )
{
VstMidiEvent *e = (VstMidiEvent *) m_events->events;
..etc

Post

Jeff McClintock wrote:Also bear in mind you don't usually need to copy the events sent from the host, the pointer to the host's events passed by processEvents() remains valid during process(). Rather than laboriously making a copy of the events, just copy the pointer...

long SeVst::processEvents (VstEvents* events)
{
m_events = events;
return 1; // want more
}

void SeVst::processReplacing(float **inputs, float **outputs, long sampleframes)
{
if( m_events )
{
for( int i = 0 ; i < m_events->numEvents ; i++ )
{
VstMidiEvent *e = (VstMidiEvent *) m_events->events;
..etc


Indeed.. while this might seem theoretically "against the spec" it's something that every practical host must support anyway, because plenty of us have been doing this for ages. Just make sure you always clear the pointer at the end of the processReplacing call (and I'd clear it in suspend() and/or resume() as well, just to be safe).

Post

You guys are brave. Can you really get away with that in ALL hosts? (FLS typically being the one with the least generous interpretation of the spec. If you don't plan a contingency for EVERYTHING and EVERYTHING, that host will bite you!)

Post

thank you guys so much for the explanation. now I have a clear picture how everything is running :)

Post

mystran wrote:
Jeff McClintock wrote:Also bear in mind you don't usually need to copy the events sent from the host, the pointer to the host's events passed by processEvents() remains valid during process(). Rather than laboriously making a copy of the events, just copy the pointer...
Indeed.. while this might seem theoretically "against the spec" it's something that every practical host must support anyway.
No, not against the spec. Why would Steinberg design the spec to force you to copy some memory that's already allocated for you? Why would you want to waste cycles in a real-time context?

ALL hosts maintain the event list during the process call. That is the spec. No need to overcomplicate your code.

Post

Jeff McClintock wrote:No, not against the spec. Why would Steinberg design the spec to force you to copy some memory that's already allocated for you? Why would you want to waste cycles in a real-time context?

ALL hosts maintain the event list during the process call. That is the spec. No need to overcomplicate your code.
Not against the spec, but also not in the spec - the VST SDK 2.4rev2 documentation doesn't say anything about the lifetime of the events. While the behavior would make sense, it's pure conjecture that ALL hosts maintain the event list.

That said, mine do 8-)
"Until you spread your wings, you'll have no idea how far you can walk." Image

Post

arakula wrote:
Jeff McClintock wrote:No, not against the spec. Why would Steinberg design the spec to force you to copy some memory that's already allocated for you? Why would you want to waste cycles in a real-time context?

ALL hosts maintain the event list during the process call. That is the spec. No need to overcomplicate your code.
Not against the spec, but also not in the spec - the VST SDK 2.4rev2 documentation doesn't say anything about the lifetime of the events. While the behavior would make sense, it's pure conjecture that ALL hosts maintain the event list.

That said, mine do 8-)
Absolutely.

Also, nothing to say processEvents will only be called once between process calls. (If at all!) Or that the events will be sorted in order of their deltaFrames values.

And again, if you want to test under the worst case, least generous, assumption-smashing host possible, its name is FLS. It's like they went out of their way to find ambiguity in the VST API and chose the path of most resistance at every point.

:?

Post Reply

Return to “DSP and Plugin Development”