• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Stereo Processing
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Stereo Processing


  • Subject: Re: Stereo Processing
  • From: William Stewart <email@hidden>
  • Date: Fri, 23 Mar 2007 19:11:28 -0700


On 22/03/2007, at 12:48 PM, paul Fultz wrote:

thanks for the help, i got it to work, except now i
cant get the bypass to work, i copied the code from
AUEffectBase, to try and make sure it was right, i
copied GetProperty(), GetPropertyInfo(),
SetProperty(), and i copied the bypass funcions, and
mBypassEffect varaible and initialize it to false like
in the AUEffectBase, but still auval says it is not
supported, i dont know why, also i delete the
ProcessInPlace() stuff, i dont know what that is
exactly, do i need ProcessInPlace to implement bypass?

No, process in place is very nice optimisation (but only applicable for N-N channel processing of course).


Bypass would minimally require:
GetPropertyInfo to say the property is supported (size of UInt32 and isWritable is true of course)
GetProperty to return a UInt32 (am I on or off)
SetProperty to allow you to set it on and off


That is all auval can test - so a simple case to get this going is to create a member variable mBypassIsOn and use it in the above three calls

Once you have auval recognising that you implement this, then go and actually implement it in your render call I think (that would be how I'd approach it)


also, auval gives me a warning saying it can initialize unit to un-supported num channels to input channel:1 output channels:2, and input channel:1, and output channel:4, etc . . ., but the thing is in Render() it supports 1-2, and 2-2, so how do i setup my audio unit to only allow initializing to these combinations of channels? thanks in advance for all the help. im new to this. and really appreciate it.

Sure - Have a look at the Initialise call in AUEffectBase - all You have to do the following: (1) Provide this for your effect class: bool MyAUEffect::StreamFormatWritable( AudioUnitScope scope, AudioUnitElement element) { return IsInitialized() ? false : true; }

(that is, don't allow the stream format to be changed if your AU is initialised)

(2) You have to tell everyone what channel capapilities you support: I think your case is either { mono in, stereo out } or { stereo in, stereo out } - so your channel capabilities would be:

UInt32 MyAUEffect::SupportedNumChannels (const AUChannelInfo** outInfo)
{
static const AUChannelInfo sChannels[2] = { {1, 2}, {2, 2} };
if (outInfo) *outInfo = sChannels;
return sizeof (sChannels) / sizeof (AUChannelInfo);
}


(3) Have a look in AUEffectBase::Initialise
- it has a broad implementation to make sure the formats of the AU match what your AU says it is capable of. Your version of init (with the above channel capabilities) would be a simple as:


if (inputChans == 1) {
	if (outputChans != 2) fail
}
if (inputChans == 2) {
	if (outputChans != 2) fail
}

That should be it I think

Bill


Paul

--- William Stewart <email@hidden> wrote:

Here's a modification of some code we use internally
- the DSP
decision can be done more optimally based on what
your code ends up
doing...


ComponentResult AUMatrixReverb::Render ( AudioUnitRenderActionFlags &ioActionFlags, const AudioTimeStamp & inTimeStamp, UInt32 framesToProcess) { AUOutputElement *theOutput = GetOutput(0); AUInputElement *theInput = GetInput(0); // get input source audio AudioUnitRenderActionFlags xflags = 0; ComponentResult result = PullInput(0, xflags, inTimeStamp, framesToProcess);

	if (result) return result;

/*
this part uses an internal object to keep a track of
any silent
input, adjust for our
decay/tail time and determine if it will actually
produce data. If it
doesn't then we just return
a silent output buffer.

This is a nice optimisation, but can be bypassed
initially

	bool silence = xflags &
kAudioUnitRenderAction_OutputIsSilence;

	mSilentTimeout.Process(framesToProcess,
(SInt32)(GetTailTime() *
GetSampleRate() ), silence );

	if(silence)
	{
		ioActionFlags |=
kAudioUnitRenderAction_OutputIsSilence;

		// clear out the destination buffer to match
silent bit
	

AUBufferList::ZeroBuffer(theOutput->GetBufferList());
		return noErr;	// silent output so tail should have
died down by
now; no need to process this time
	}
	else
	{
		// not silent output this time
		ioActionFlags &=
~kAudioUnitRenderAction_OutputIsSilence;
	}
*/

	int nOutChannels =
theOutput->GetStreamFormat().mChannelsPerFrame;
	int nInChannels =
theInput->GetStreamFormat().mChannelsPerFrame;

	// call the DSP code - special case stereo->stereo
	if (nInChannels == 2 && nOutChannels == 2)
	{
		mDSP->Process(	theInput->GetChannelData(0),
						theInput->GetChannelData(1),
						theOutput->GetChannelData(0),
						theOutput->GetChannelData(1),
						framesToProcess );
	}
	else if (nInChannels != nOutChannels)
	{	// if you want to do mono-stereo (or any N-M
channel processing
you need to take care of this
		result = unimperr;
	}
	else
	{
		// N-N channel processing
		for (unsigned int i = 0; i < nInChannels; ++i) {
			float* inputChannel =
theInput->GetChannelData(i);
			float* outputChannel =
theOutput->GetChannelData(i)
			mDSP->Process(	inputChannel, outputChannel,
framesToProcess );
	}

	return result;
}

Bill

On 18/03/2007, at 6:39 PM, paul Fultz wrote:

ok thanks for the information, so if i overide
AUBase
instead all I would need to do is overide Render()
and
Reset(), right? and how would i go about coding
the
Render() so that i can call Process()? i was
working
on some of the code here i dont know if this is
correct, i kind of just compiled it together from
looking at other code:
ComponentResult		AUStereoBase::Render(
AudioUnitRenderActionFlags &	ioActionFlags,
											const AudioTimeStamp &			inTimeStamp,
											UInt32							inNumberFrames)
{
	bool ioSilence = IsInputSilent (ioActionFlags,
inFramesToProcess);
	ioActionFlags |=
kAudioUnitRenderAction_OutputIsSilence;
	AUInputElement *input = GetInput(0);
	AUOutputElement *output = GetOutput(0);

	AudioUnitRenderActionFlags xflags = 0;
	ComponentResult result = PullInput(0, xflags,
inTimeStamp, inFramesToProcess);
	if (result) return result;

	Float32 *sourceLeftP = input->GetChannelData(0);
	Float32 *sourceRightP = input->GetChannelData(1);
	Float32 *destLeftP = output->GetChannelData(0);
	Float32 *destRightP = output->GetChannelData(1);
	Process(sourceLeftP,
sourceRightP,destLeftP,destRightP,
inNumberFrames,ioSilence);
	return noErr;
}
also Process() is a virtual funcion in the class
AUStereroBase, which i will overide in my AU
class.
also how can read number of channels in? i want do
something different if the input is mono, like
call
Process() in this way:
Process(sourceLeftP,
sourceLeftP,destLeftP,destRightP,
inNumberFrames,ioSilence);

thanks,
Paul

--- William Stewart <email@hidden> wrote:

We generally overide AUBase and just implement
the
Render method -
then instead of working around all this stuff,
you
just implement
what you need. I think its clearer and easier
(but
many have ignored
me in the past!)

Bill

On 16/03/2007, at 6:47 AM, Christian Luther
wrote:

Hi Paul!

Unfortunately there is more work to do. You also
have to modify the
function that creates the kernels
(MaintainKernels()) so that you
have your stereo kernel set up correctly (it
usually creates one
kernel per I/O which is not what you want). If
you
want to support
stereo processing only you can just create one
instance of your
Stereokernel. If you want to support both mono
and
stereo
processing you will have to do some more work
there.
Then, you have to modify ProcessBufferLists()
which is the function
that finally calls the Process() functions of
the
kernels.

I can't really remember the details, but just
look
around the
methods I named and try to understand what they

=== message truncated ===




______________________________________________________________________ ______________
Finding fabulous fares is fun.
Let Yahoo! FareChase search your favorite travel sites to find flight and hotel bargains.
http://farechase.yahoo.com/promo-generic-14795097

--
mailto:email@hidden
tel: +1 408 974 4056
________________________________________________________________________ __
"Much human ingenuity has gone into finding the ultimate Before.
The current state of knowledge can be summarized thus:
In the beginning, there was nothing, which exploded" - Terry Pratchett
________________________________________________________________________ __


_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


References: 
 >Re: Stereo Processing (From: paul Fultz <email@hidden>)

  • Prev by Date: How to print individual MusicTrack events?
  • Next by Date: Re: How to print individual MusicTrack events?
  • Previous by thread: Re: Stereo Processing
  • Next by thread: What is the easiest way to create and use ADSR envelope
  • Index(es):
    • Date
    • Thread