Re: [linux-audio-dev] more on XAP Virtual Voice ID system

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: Re: [linux-audio-dev] more on XAP Virtual Voice ID system
From: Tim Hockin (thockin_AT_hockin.org)
Date: Wed Jan 08 2003 - 10:09:56 EET


> > 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.


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : Wed Jan 08 2003 - 10:11:31 EET