On Tuesday 07 January 2003 01.55, Tim Hockin wrote:
1. Recv VOICE_ON, allocate a voice struct
2. Recv VELOCITY, set velocity in voice struct
3. No more events for timestamp X, next is timestamp Y
4. Process audio until stamp Y
4.a. Start playing the voice with given velocity
Problem is step 1. If the voice allocator looks at velocity, it
won't work, since that information is not available when you do
the allocation. Likewise for setting up waveforms with velocity
maps and the like.
When are you supposed to do that sort of stuff? VOICE_ON is what
triggers it in a normal synth, but with this scheme, you have to
wait for some vaguely defined "all parameters available" point.
So maybe VOICE creation needs to be a three-step process.
* Allocate voice
* Set initial voice-controls
* Voice on
This way the instrument is alerted to the fact that a new voice is
being created without deciding which entry in the velocity map to
use.
...and then there's no need for a DETACH_VVID event either, as the
"allocate voice" event implies that whatever VVID it uses will be
used for a new note for now on, regardless of what that VVID might
have been used for before.
Two problems solved! (Well, almost... Still need temporary space for
the "parameters", unless voice allocation is non-conditional.)
This is essentially saying that initial parameters
are
'special', and they are in many-ways (I'm sure velocity maps are
just one case).
Yes; there can be a whole lot of such parameters for percussion
instruments, for example. (Drums, cymbals, marimba etc...)
Or we can make the rule that you do not choose an
entry in a
velocity map until you start PROCESSING a voice, not when you
create it. VOICE_ON is a placeholder. The plugin should see that
a voice is on that has no velocity-map entry and deal with it whn
processing starts. Maybe not.
No, I think that's just moving the problem deeper into synth
implementations.
[...]
Actually, it
doesn't know anything about that. The physical
VVID->voice mapping is a synth implementation thing, and is
entirely dependent on how the synth manages voices.
s/voice/VVID/, and you get closer to what VVIDs are about.
But it COULD. This could become more exported. The plugin tells
the host what it's max polyphony is (a POLYPHONY control?). The
host manages voices 0 to (MAX_POLY-1) for each synth.
That doesn't really work for normal polyphonic instruments, unless
the host *fully* understands the synth's voice allocation rules,
release envelopes and whatnot. The polyphonic synth is effectively
reduced to a tracker style synth with N monophonic channels.
The POLYPHONY could be interesting, though, but I think most things
you can do with it should really be done with monophonic channels...
0-VVID is just so you can have one control for voice
on and
off. Positive means ON, negative means OFF. abs(event->vvid)
is the VVID.
Ok. Why not just use the "value" field instead, like normal Voice
Controls? :-)
Because VOICE is actually a channel control?
But it's really just a per-Voice on/off switch, right? (It's just
that you don't address voices directly, but you never do that anyway.)
I dunno, being thick,
probably. :) VOICE(vid, 1) and VOICE(vid, 0) are the notation I
will use to indicate that a voice 'vid' has been turned on or off.
:)
Ok. Well, those look like Voice Controls to me. :-)
Not really -
but whoever *sends* to the synth will care, when
running out of VVIDs. (Unless it's a MIDI based sequencer, VVID
management isn't as easy as "one VVID per MIDI pitch value".)
Ahh, this does get interesting.
Yep. I ran into it when I started messing with VVIDs in Audiality.
For the MIDI sequencer, one can just grab one VVID for each MIDI
pitch for each channel and bo done with it, but for the future
"native" sequencer (no MIDI crap), there won't be any fixed limit on
the number of voices you can control on one channel, and no fixed
relation between "pitch" and "ID"...
way you can
know when it's safe to reuse a VVID. (Release
envelopes...) Polling the synth for voice status, or having
synths return voice status events doesn't seem very nice to me.
The very
It seems to me that voice allocation and de-allocation HAS to be a
two-way dialogue, or you have use-once VVIDs. Maybe this is OK -
2^32 VVIDs per synth. The host only really needs to store a small
number - the active list.
Why would the host (or rather, sender) care about the VVIDs that are
*not* active? (Remember; "Kill All Notes" is a Channel Control, and
if you want per-voice note killing, you simply keep your VVIDs until
you're done with them - as always.)
My point is that when the host/sender no longer cares about a voice,
it can grab the VVID and tell the synth to allocate a new voice for
it. Whether or not that results in a voice without a VVID is
irrelevant, since when the host/sender reuses the VVID, it
*explicitly* says it no longer cares about whatever voice might have
been assigned to that VVID.
Obviously it can't be a linear index
EVER, but it makes a fine hash key or index modulo N.
Yeah - but then we're back at square one, basically... (And I doubt
hashing is much point for "sane" voice counts.)
1) Voice
Control. (Keep the VVID for as long as you need it!)
2) Channel Control. ("Kill All Notes" type of controls.)
My header already has a 'stop all sound' event. :)
Cool. :-)
Although the
VOICE control might actually be the VELOCITY
control, where anything non-0 means "on"... A specific,
non-optional VOICE control doesn't make sense for all types of
instruments, but there may be implementational reasons to have it
anyway; not sure yet.
VELOCITY can be continuous - as you pointed out with strings and
such. The creation of a voice must be separate in the API, I
think.
Why? It's up to the *instrument* to decide when the string (or
whatever) actually starts to vibrate, isn't it? (Could be VELOCITY >=
0.5, or whatever!) Then, what use is it for hosts/senders to try to
figure out where notes start and end?
This all needs more thinking. I haven't had too
much time to think
on these hard subjects the past two weeks, and I might not for a
few more. I'll try to usurp work-time when I can :)
This all leads me back to my original thoughts, that the
voice-management MUST be a two-way dialog. I don't like the idea
of use-once VVIDs because eventually SOMEONE will hit the limit. I
hate limits :)
Of course - but I don't think it has to be a two-way dialog for this
reason. And I don't think a two-way dialog can work very well in this
context anyway. Either you have to bypass the event system, or you
have to allow for quite substantial latency in the feedback direction.
Maybe synths need to have a bunch of Virtual Voices, as well as
Physical Voices? Virtual Voices would basically be stripped, "dead"
voice structs, that just track Voice Controls for VVIDs without
Physical Voices.
Then there would be two levels of "overload":
Out Of Physical Voices:
* Synth starts allocating Virtual Voices for VVIDs.
* All Voice Controls are still tracked.
* Synth may actively reevaluate Voices, switching
VVIDs from/to Physical Voices as desired.
Out Of Virtual Voices:
* Synth starts hooking VVIDs up to the "NULL Voice",
and/or starts doing instant voice stealing.
* Voice Controls may be ignored!
* Voice allocation may be suboptimal.
Note that when a synth starts stealing voices, that's actually *error
handling* going on. If a soft synth with say, 32 physical and 32
virtual voices runs out of *virtual voices*, you're deep in it; that
is nothing but serious abuse! You'll probably want to increase the
polyphony long before you get to the "50% of voices are ignored"
point.
more thought needed
Yes...
//David Olofson - Programmer, Composer, Open Source Advocate
.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`--------------------------->
http://olofson.net/audiality -'
---
http://olofson.net ---
http://www.reologica.se ---