On Tuesday 10 December 2002 02.15, Tim Hockin wrote:
struct
XAP_bay_descriptor
{
const char *name;
XAP_channel_type channel_type;
int min_channels;
int max_channels;
/*
* Maybe some other stuff
*/
};
If you like, you may have several Bays with Audio Input Channels,
for example. These would be totally independent WRT min/max
channel counts, audio format or whatever properties Audio
Channels may have.
So let me see if I get the the containership correct:
a Plugin has n Bays
a Bay has m Channels
Correct.
a Channel has p Controls and q Ports
Well, a Channel can have p Controls OR p Audio Ports. I would say
that a Channel can vave p *Slots* - where a slot can be one of:
Audio Input Slot
Audio Output Slot
Control Input
Control Output
Event Ports don't really belong in this picture. They're like a
flexible resource that the Plugin may use pretty much as it desires.
They are owned by the Plugin instance, and their relation to Bays,
Channels, Controls, phase of the moon or whatever, is controlled
entirely by the Plugin.
When asked to connect a Control Input, a Plugin will hand you the
address of a suitable Event Port, as well as a 32 bit Control ID that
the Plugin may encode in any way it feels like. (As described in an
earlier post.)
This is how you can chose between single Port/one Port per
Channel/one Port for every N Channels/one Port per Control or
whatever you might find useful, efficient or just generally cool.
I know at some point you started thinking of event
ports as
separate channels.
Actually, one event port per channel. Then I realized you don't have
to specify this in the API at all!
I am almost convinced that different channel
kinds are needed, but Bays has thrown me.
Bays are actually a way of grouping channels of the same kind
together. I initially called them "Channel Kinds", until I realized
that I had already "invented" the term "Bay" for exactly this thing
for MAIA.
This is what I was
thinking about as I slept (weird dreams...)
You have those too? :-)
Plugin {
/* everything has master controls */
n_master_controls;
master_controls[];
Yeah, since there will probably be a few "system" events that plugins
*must* implement anyway... Or maybe not. No big deal. We'll see.
n_master_eventports;
master_eventports[];
These won't be public. (See above.)
/* many plugins will have 1 template, but they can
have more.
* multi-timbral instruments (synth part, drum part, ...) and
mixer * slots (mono, stereo, ...) come to mind
*/
n_channel_templates;
channel_templates;
This sounds pretty much like my Bays. You have one template for each
"kind" of channel you want, and then you can have varying numbers of
channels of each kind?
/* mixers might start with 0, synths might start with
any #,
simple * instruments might start with 1.
*/
n_channels;
n_channels_min;
n_channels_max;
channels[n_channels_min];
}
Still a 1D array of channels, that is?
I'm thinking about Bays as an array of objects that each has an array
of Channels - but it doesn't have to be that way physically,
obviously. I just think it seems easier with arrays of arrays (2D)
since Bays have independent Channel counts, that might even change
during the lifetime of the plugin. (That's another issue we have to
deal with...)
Eventport {
label;
name;
/* anything else? */
}
Mine look like this:
typedef struct AEV_port
{
/*
* Note that when 'first' is NULL, 'last' is undefined!
* (If there's no first event, there can't be a last
* event either - makes sense, eh? :-)
*/
AEV_event *first;
AEV_event *last;
const char *name;
} AEV_port;
But again, note that this is a very low level thing, that plugin and
host code well nearly always treat as an opaque data type. It's part
of the API, but ports don't have public names or anything. (My name
field is only for debugging, so you can look at a port and see where
it belongs.)
ChannelTemplate {
label;
name;
/* could be split to per-channel and per-voice */
n_controls;
controls[];
Well, it just happens that channel + voice control is a very
practical model for most synths. It's probably not perfect and
without restrictions, but I think we can do a lot of cool stuff
before seeing much of these issues.
Anyway, I can see two ways of handling this:
1. Have two control ranges for Event Input Channels.
2. Allow only one range of controls per Event Input Channel,
and instead, use an extra bay of Voice Control Channels, if
you want Voice controls. One could mark the Bays with hints
suggesting that they are closely related.
Now that the strict physical relation between channels and Event
Ports is eliminated, this doesn't matter at all performance wise, but
it might make the API a bit cleaner.
n_eventports;
eventports[];
n_inports;
n_outports;
}
I'd rather think of Bays as being in/out neutral, and use different
Channel types for input and output. Only one array of Bays needed
that way.
[...]
Number of Bays
hardcoded or not?
Assuming that we're using different words to get the same idea, no.
A Mixer would start with 0 Channels and (for example) 4
ChannelTemplates (MONO_STRIP, STEREO_STRIP, MONO_BUS, STEREO_BUS) .
The host would somehow direct the plugin to add a new MONO_STRIP
for each incoming connection and a STEREO_BUS for output. Just as
ideas..
Yeah, that sounds like what I have in mind. It's just that it creates
some nasty issues for RT engines...
You can now have different controls, different numbers
of audio
in/outs, and different event ports per Template. And you can
instantiate as many instances of each template as needed via
plug->new_channel(template_num).
I see. Bays would be different from Templates in that each Bay can
have only *one* kind of objects in it. It means that relationships
between for instance control inputs and audio outputs cannot be
expressed by grouping them together - but I think we have concluded
earlier that this is not very useful anyway.
Linking Bays WRT Channel count may be useful, though... (If you have
a mixer, you'd probably want exactly one strip automation control
input for each stip audio input. :-)
BTW, this multichannel "group" issue... That "granularity" (or
"group_size" or whatever) field would be in the Bay, and would still
effectively say "for one imaginary channel, you actually need N real
channels". This would make that Bay linking a whole lot more useful,
since it would allow M Channels on one Bay to correspond to N
Channels on another.
[...]
//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 -'
.- M A I A -------------------------------------------------.
| The Multimedia Application Integration Architecture |
`---------------------------->
http://www.linuxdj.com/maia -'
---
http://olofson.net ---
http://www.reologica.se ---