Re: AUEffectBase and Stream formats
Re: AUEffectBase and Stream formats
- Subject: Re: AUEffectBase and Stream formats
- From: Marc Poirier <email@hidden>
- Date: Fri, 2 May 2003 22:27:55 +0200 (CEST)
Bill,
Now that the new SDK is upon us, I've started thinking about this again.
So... if you can convince me that it really would require some major
paradigm shift in AUEffectBase to support non-N-to-N effects, then I will
sit down and be quiet about this. But as things are now, I don't think it
would be a big deal at all and I also think that it's important to support
this.
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.
I also remembered something else now. I knew that, for some reason, I was
finding it annoying being told at this point that AUEffectBase is only
expected to do N-to-N processing. I thought that I remembered that there
was something in AUEffectBase.h about this, and here it is:
"If your unit processes N to N channels, and there are no interactions
between channels, it can override NewKernel to create a mono processing
object per channel. Otherwise, don't override NewKernel, and instead,
override ProcessBufferLists."
So that's the approach I've been taking with many plugins. I use
AUEffectBase and override ProcessBufferLists if I have interactions
between channels and also SupportedNumChannels if I only support specific
configs. But now it sounds like what you're saying is contradicting the
advice in AUEffectBase.h.
Okay, well, I think that's about all that I have to say about why I think
that AUEffectBase should support non-N-to-N effects, now I'd also like to
talk about whether or not this would require any major changes to the
AUEffectBase class. I don't think that it would, but maybe I'm just not
aware of some things. In addition to what you say about having Initialize
look like this:
ComponentResult AUEffectBase::Initialize()
{
if (SupportedNumChannels() == 0) {
if ((GetNumberOfChannels() != GetInput(0)->GetStreamFormat().mChannelsPerFrame) || (GetNumberOfChannels() == 0))
return kAudioUnitErr_FormatNotSupported;
}
MaintainKernels();
return noErr;
}
I think that there's only one other change that needs to be made. The
change is that ChangeStreamFormat needs to be tweaked. This is what I
currently do in my plugins, and I think it's all that's necessary:
ComponentResult DfxPlugin::ChangeStreamFormat(blah, blah, blah)
{
const AUChannelInfo *auChannelConfigs = NULL;
UInt32 numIOconfigs = SupportedNumChannels(&auChannelConfigs);
if ( (numIOconfigs > 0) && (auChannelConfigs != NULL) )
{
SInt16 newNumChannels = (SInt16) inNewFormat.mChannelsPerFrame;
bool foundMatch = false;
for (UInt32 i=0; i < numIOconfigs; i++)
{
switch (inScope)
{
case kAudioUnitScope_Input:
if (newNumChannels == auChannelConfigs[i].inChannels)
foundMatch = true;
break;
case kAudioUnitScope_Output:
case kAudioUnitScope_Global:
if (newNumChannels == auChannelConfigs[i].outChannels)
foundMatch = true;
break;
default:
// just ignore it for now, since it's unknown what it's for
foundMatch = true;
break;
}
}
if (!foundMatch)
return kAudioUnitErr_FormatNotSupported;
}
That needs to be the first thing that is done in
AUEffectBase::ChangeStreamFormat, then you can carry on to the rest of the
stuff that's already there. You just want to make sure that this is done
before calling AUBase::ChangeStreamFormat, which may accept the stream
format and save it, even though it may be invalid.
So aside form that, is there anything else in AUEffectBase that might
break? Or does it seem like these two tweaks might be reasonable for
AUEffectBase, and therefore allow the class to support freak of nature
effects that require mismatched channel valences? :)
Thanks for listening,
Marc
At 4:41 PM -0800 3/29/03, Bill Stewart wrote:
>
I'd thought of doing this:
>
>
if (SupportedNumChannels() == 0) {
>
do the channel equiv test
>
// no else - presume its correct
>
}
>
Init
>
>
But, really the AUEffectBase only works with in and out streams where
>
the channel valence matches - and I'm not comfortable having that test
>
there because it presumes alot of other work has been done to the class
>
- at that point its not unreasonable to make you also do the work to
>
initialize correctly.
>
>
Otherwise, I believe the implementation is making a false promise to
>
you...
>
>
As for taking care of say an effect that only does 2->2 (and thus
>
provides the SupportedNumChannels support), that AU will also need to
>
make sure that AUEffectBase::ChangeStreamFormat is overwritten anyway
>
to validate the num channels in the proposed new stream format - that
>
is definitely the correct place to validate the format for this
>
restriction (not Initialize)
>
>
So, by the time it gets to Initialize as far as the provided
>
implementation is concerned, those channel valences should match...
>
>
For those effects (like AUMatrixReverb) that can do different channel
>
valences, we subclass AUBase currently. We've talked about making a
>
more serviceable subclass for these kinds of effects - but haven't done
>
that yet.
>
>
Bill
>
>
On Saturday, March 29, 2003, at 03:34 PM, Marc Poirier wrote:
>
>
> This all sounds to me like good changes, but I have one concern:
>
>
>
>> Secondly, I'd like to tighten up the enforcement of the assumption
>
>> that
>
>> an Effect that doesn't publish a custom set of channel valences on in
>
>> and output, will ONLY accept matching input and output channel
>
>> numbers.
>
>>
>
>> So, here's the changes. I've tested these with our AUs in both Logic
>
>> and Spark and don't see any problems.. I'd like to see some more
>
>> testing (which I'll try myself... but confirmation would be nice:)...
>
>>
>
>> ComponentResult AUEffectBase::Initialize()
>
>> {
>
>> // This base class only supports effects that have the same number
>
>> // of channels in and out - so we check here that this is the case
>
>> if ((GetNumberOfChannels() !=
>
>> GetInput(0)->GetStreamFormat().mChannelsPerFrame) ||
>
>> (GetNumberOfChannels() == 0))
>
>> {
>
>> return kAudioUnitErr_FormatNotSupported;
>
>> }
>
>>
>
>> MaintainKernels();
>
>> return noErr;
>
>> }
>
>
>
> Why does the base class only support n-to-n configurations? It seems
>
> to me a bit redundant that an AU that inherits from AUEffectBase and
>
> which supports non-n-to-n configs (and doesn't use kernels) will need
>
> to both override Initialize and do format negotiation there, and
>
> also override SupportedNumChannels and specify its allowable i/o
>
> configs. I would personally prefer that AUEffectBase::Initialize
>
> call SupportedNumChannels and include that info as a basis for its
>
> format negotiation (if a non-zero value is returned).
>
>
>
> 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.