[gmpi] Re: Parameters / controls / GMPI event system - refreshment

  • From: Chris Grigg <gmpi-public@xxxxxxxxxxxxxx>
  • To: gmpi@xxxxxxxxxxxxx
  • Date: Wed, 30 Nov 2005 15:25:16 -0800

On Tuesday, November 29, 2005 10:23 PM [GMT+1=CET],
thockin@xxxxxxxxxx <xxxthockin@xxxxxxxxxxxxx> wrote:

On Tue, Nov 29, 2005 at 12:24:42PM -0800, Chris Grigg wrote:

 (1) One of the examples had messages addressed to things called v0 &
 v1, but usually you want the plug to do voice allocation.  So what's
 up with that?

Virtual voice IDs. The host has an idea of all the voices it has requested be started. Thos voices map to real voices inside the plugin according to plugin-defined rules. The host should only operate on virtual voices.

In some (very primitive) system I once made, when you started a new "note" (I actually prefer "musical object" but anyway...) you can send the "start new note" event to the plugin that must start a new voice for it, and the plugin returns a voice ID, that the host can store for later referencing. I also seem to recall I added the possibility for the host to specify the voice ID directly that should be used for the new voice (instead of letting the plugin choose one), but I don't really recall why I added that... The plugin can assign its voices as it sees fit, but should let the host know the ID of the voice for later reference. There's just one thing I remember not being sure about how to handle it: a note off message does not kill the voice right away, and the corresponding voice ID will be alive for the rest of the release part of that note, during which you may stil want to bend its pitch etc... The time when the note really stopped is determined by the plugin itself, and in order to let the host know that the voice has eventually completely died, there should be a mechanism that allows the plugin to tell the host that the corresponding voice ID has become free again. Does this sound reasonable?

Sure, or else:

1) host to plug: newNoteID = thePlug->getFreeNoteID()
2) host sends whatever messages to plug, all using the newNoteID
3) when that note event reaches its natural death within the plug, if any, the plug calls back to host: theHost->noteIdHasDied( thisPlug, thisPin, deadNoteID )
Then the host knows when it makes no sense to keep sending events to that note any more.

But this only makes sense if you want to really expose the plug's note ID internals to the host, which seems unnecessarily complicated. Alternatively, you could keep the noteIdHasDied() callback idea but simply make the host responsible for keeping the note IDs it uses mutually unique. Then once the host starts using a given note ID, it can't be re-used until and unless the plug issues a noteIdHasDied() callback for that note ID. Not hard, especially with a host helper lib, and it simplifies all the plugs.

Just another take on the same idea... there are lots of ways to do these things, and what's best depends on what your goals are. Therefore: Requirements first!

>> (2) If you separate out all the parameters into separate messages,
 how does the plug know when the sender's finished sending parameters?
 If it's just waiting for the 'turn note on' message, then

To keep up this particular example idea: You send all of the parameters that apply to the start of a voice at the same timestamp as the voice-on. When you hit the next timestamp, you've got them all and can process that voice-on.

 (a) is it -really- reasonable to rely on senders to always do the
 'turn note on' message last?

 (b) Can you -really- rely on the pipes to always preserve message
 transmission order (think TCP/IP etc.)?

Nope. I have somewhere an older email that talks about this - you need to process all the events for a sample frame before generating audio for that frame.

That's more or less similar to what is done in VST now when you're using MIDI events to get sample-accurate parameter changes, right? First the host calls your plugs processEvents function during which you receive all MIDI events for the about-to-be-processed audio buffer, and only then the process function is called that actually does the audio processing stuff, taking into account the timestamps and semantics of the parameter changes that are done via the MIDI events (usually CC's).


But my point still holds: you still need to get the order of arrival right, because one message may undo the action of another. If the order is swapped, the performance is, uhm, inverted or something.

        -- Chris G.

Generalized Music Plugin Interface (GMPI) public discussion list
Participation in this list is contingent upon your abiding by the
following rules:  Please stay on topic.  You are responsible for your own
words.  Please respect your fellow subscribers.  Please do not
redistribute anyone else's words without their permission.

Archive: //www.freelists.org/archives/gmpi
Email gmpi-request@xxxxxxxxxxxxx w/ subject "unsubscribe" to unsubscribe

Other related posts: