Re: AUEffectBase and Stream formats
Re: AUEffectBase and Stream formats
- Subject: Re: AUEffectBase and Stream formats
- From: Marc Poirier <email@hidden>
- Date: Sun, 4 May 2003 19:40:56 +0200 (CEST)
Well... since my last message to the list was just rejected for being too
large, and since the code snippets wrapped terribly anyway, I'm re-posting
this with code snippets removed and placed on the web instead.
>
> To me, and I think to most people approaching the AU SDK, AUEffectBase
>
> is where you would logically start from to make an effect plugin. It
>
> sounds like you're saying that a plugin that doesn't process the same
>
> number of ins as outs is not considered to be an effect. To me, this
>
> distinction just doesn't make sense. I don't understand this
>
> limitation in defining what's an effect. Right now, I'm working with
>
> a friend on his granular synthesis plugin that takes mono input and
>
> provides some stereo random placement of grains, so it has stereo
>
> output. To me, this is still an effect and it seems to me an
>
> unecessary nuisance to start from AUBase, since I'll just wind up
>
> redoing all the stuff in AUEffectBase.
>
>
We do exactly the work that you describe above for the Matrix Reverb
>
and its not a great deal of work..!
>
The real advantage of AUEffectBase is the provision of kernels to allow
>
simple channel by channel processing of n-n effects (by far I think the
>
most common case - at least common enough)
Hmmm, I'm not sure I agree. AUEffectBase also handles the BypassEffect
and InPlaceProcessing properties, handles format change rejections if the
AU is Initialized, handles parameters with sampling rate dependencies,
handles rendering slice chopping for intra-buffer parameter changes,
handles buffers properly in Render, and provides several handy convenience
methods. I know that it's not a great deal of work to redo this stuff,
but it's a lot of copy and paste (most of AUEffectBase.cpp), which (1)
I've learned is not a good programming practice (maintaining the exact
same code in multiple places) and (2) indicates to me that AUEffectBase
has enough useful stuff for effects in general, not just n-to-n effects,
that it should cover non-n-to-n effects.
>
> In addition to what you say about having Initialize
>
> look like this:
>
>
Your code looks like its correct - but it isn't.
>
>
Basically AUChannelInfo CAN describe N->M channel possibilities - but
>
it can also describe two other kinds of relationships:
>
Firstly:
>
2 2
>
2 5
>
>
Now:
>
-1 -1
>
4 -1
>
>
Or even:
>
-1
>
-2
>
>
What do these mean?
>
>
-1 and >0 mean any number of channels on the -1 scope to N channels on
>
the >0 scope
>
-1 and -1 mean any number of channels either scope as long as they
>
match (this is the default for AUEffect derived effects if you like)
>
-1 and -2 mean any number of channels on either scope - can or cannot
>
match.
Ahhh, you're right, I did forget about the -1 option. However, all of
this other stuff (-1 and -1 means that in = out, -1 and -2 means that they
can be unequal) is not mentioned anywhere in the headers or docs. Only -1
is mentioned as meaning any number of channels. But anyway, that's a
documentation problem...
>
So - the problem is this.
>
>
ChangeStreamFormat cannot validate that the channels match -
>
particularly in the case where you have -1 on one scope and >0 on the
>
other BECAUSE formats are changed sequentially:
>
Lets say you have:
>
-1 2 4
>
-1 5 5
>
>
You start at being 2/2 and the user is putting you to 4/5 - now you can
>
validate that you are getting say 4 on the input scope but it would be
>
incorrect to invalidate the format because the output scope doesn't
>
match - but you still don't know yet if you've been set up correctly
>
and you don't know which order you are going to have your formats set -
>
but at this point you do have an invalid format 4/2...
>
>
The only place you CAN validate this is in Initialize
>
>
This gets even more complicated if you add
>
-1
>
4
>
- that implies that you can accept any channels on input as long as you
>
have 4 channels on output
>
>
Does this last one sound absurd?
>
No - it is potentially what an AU that renders to Ambisonics (WXYZ)
>
might look like... (or from Ambisonics 4/-1).
>
>
So:
>
>
The correct way to do this is:
>
- ChangeStreamFormat accepts the format as it does in the SDK.
>
- Initialize has to do 2 steps
>
- If there is a channel info property it has to match the in and out
>
channels based on how that is specified (taking into account the wild
>
card matches of equal negative numbers, negative numbers on one of the
>
scopes)
>
>
- For someone deriving from AUEffectBase and using the kernels then
>
the channel numbers should match.
>
- ValidStreamFormat rejects stream formats if the unit is initialized
>
- (you could potentially not reject stream formats where there is not
>
change to the channels (say a sample rate change) - but we decided to
>
disallow this as many effects have subtle dependencies on the sample
>
rate that slip through if it is changed after initialization...
>
>
This is how AUEffectBase is implemented now - in line with the complete
>
semantic that it provides.
>
>
The extra work described above we do in AUMatrixReverb's Initialize
>
method as that is the only time (as in AUEffectBase) that you can be
>
sure that you know the state of the streams you are being given.
Alright, well you have pointed out all of the problems in my suggested
code (not handling wildcards, mis-handling the global scope), but I'm
still not convinced that it couldn't easily be done correctly and included
in AUEffectBase (including even still a bit of preemptive format rejection
in ChangeStreamFormat). ;) I've revisited my code and fixed the problems
that you've pointed out (thank you for the help), and now it looks like
this, which I think is generalized and could work a-okay in AUEffectBase:
http://destroyfx.org/AUEffectBase-MarcPatch.cpp
I do realize that the stuff in ChangeStreamFormat won't and can't catch
all invalid input or output counts. What my implementation does do is
reject them if it's plainly clear that they couldn't work in any allowable
i/o pair. But I realize that's not as important as checking the i/o pair
in Initialize and maybe it could just be discarded. I guess, like you
say, the only truly necessary change is in Initialize.
Marc
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.