[linux-audio-dev] more on XAP Virtual Voice ID system
Tim Hockin
thockin at hockin.org
Wed Jan 8 03:17:01 UTC 2003
> > The plugin sees a stream of new VVIDs (maybe wrapping every 2^32
> > notes - probably OK). It has it's own internal rules about voice
> > allocation, and probably has less polyphony than 128 (or whatever
> > the host sets). It can do smart voice stealing (though the LRU
> > algorithm the host uses is probably good enough). It hashes VVIDs
> > in the 0-2^32 namespace on it's real voices internally. You only
> > re-use VVIDs every 2^32 notes.
>
> Ok, but I don't see the advantage of this, vs explicitly assigning
> preallocated VVIDs to new voices. All I see is a rather significant
> performance hit when looking up voices.
Where a perf hit?
> Just grab a new VVID and start playing. The synth will decide when a
> physical voice should be used, just as it decides what exactly to do
> with that physical voice.
So how does a synth tell the host how it gets activated? A VOICE_ON event
tells the host and the user 'we are allocating a VVID to use'. It also
tells the synth. If the synth wants to not play anything for Velocity <
0.5, then it should just not play anything. Just because a Voice is silent,
doesn't mean it is not active. This is a separate discussion entirely from
VVIDs.
> With continous velocity, it is no longer obvious when the synth
> should actually start playing. Consequently, it seems like wasted
> code the have the host/sender "guess" when the synth might want to
> allocate or free voices, since the synth may ignore that information
> anyway. This is why the explicit note on/off logic seems broken to me.
_Your_ logic seems broken to me :) If you have a continuous controller for
Velocity, you have one voice. So you want a new voice, you use a new VVID.
How do you standardize this interface so a host can present a UI that makes
sense?
If VOICE_ON doesn't make sense for some synth, then it still makes sense for
the user.
> > Block start:
> > time X: voice(-1, ALLOC) /* a new voice is coming */
> > time X: velocity(-1, 100) /* set init controls */
> > time X: voice(-1, ON) /* start the voice */
> > time X: (plugin sends host 'voice -1 = 16')
> > time Y: voice(-2, ALLOC)
> > time Y: velocity(-2, 66)
> > time Y: voice(-2, ON)
> > time Y: (plugin sends host 'voice -2 = 17')
> >
> > From then out the host uses the plugin-allocated voice-ids. We get
> > a large (all negative numbers) namespace for new notes per block.
>
> Short term VVIDs, basically. (Which means there will be voice
> marking, LUTs or similar internally in synths.)
What is LUT? What is voice-marking? The negative VVIDs are valid for the
duration of the block, after which they use their new names. It seems
simple to me.
> > We get plugin-specific voice-ids (no hashing/translating).
>
> Actually, you *always* need to do some sort of translation if you
> have anything but actual voice indices. Also note that there must be
Because the plugin can allocate them, the plugin need not hash or translate.
It can be a direct index.
> a way to assign voice IDs to non-voices (ie NULL voices) or similar,
> when running out of physical voices.
if voice-ids are allocated by the plugin, there is no NULL voice. If you
run out of physical voices you steal a voice or you send back a failure for
the positive voice id.
> You can never return an in-use voice ID, unless the sender is
> supposed to check every returned voice ID. Better return an invalid
> voice ID or something...
Host:
send voice_on for temp vid -1
run
read events
find a voice-id -1 => new_vid
if (new_vid < 0) {
/* crap, that voice failed - handle it */
} else {
if (hash_lookup(plug->voices, new_vid)) {
/* woops, plugin stole that voice - handle it */
}
hash_insert(plug->voices, new_vid, something)
}
If the plugin wants to steal a voice, do so. If it wants to reject new
voices, do so. It is simple, easy to code and to understand.
> Well, it's an interesting idea, but it has exactly the same problem
> as VVIDs, and doesn't solve any of the problems with VVIDs. The fact
It has none of the problems of VVIDs. The only problem is that it requires
dialog.
* no carving of a VVID namespace for controller plugins
* the plugin and the host always agree on the active list of voices
* host sends voice_off no release
- plugin puts the VID in the free-list immediately
- host never sends voice_off
- plugin puts the VID in the free-list whenever it finishes
- plugin can alert the host or not
- host sends events or voice_off too late
- plugin recognizes that the voice is off and ignores events
- host sends voice_off with a long release
- plugin puts the VID in the free-list as soon as possible
- host overruns plugin's max poly
- plugin chooses a VID and stops it, returns that VID (steals the voice)
or plugin rejects new voice
what am I missing?
> search" and/or hashing), and it doesn't really buy us much, compared
> to the wrapping 32 bit VVID idea.
With a large VVID pool we still need:
host:
/* be sure we can make a new vvid */
if (cur_poly == max_poly) {
find an eligible vvid
tell the plugin it can re-use the voice on this vvid (voice_off?)
} else {
cur_poly++;
}
/* find a vvid that is not currently playing */
do {
this_vvid = vvid_next++;
while (vvid_is_active(this_vvid);
send_event(queue, VOICE_ON, this_vvid);
[voice-stealing...]
> (*Should* work, but it does require click free voice stealing without
Which is the plugin's problem in any solution we devise.
More information about the Linux-audio-dev
mailing list