Re: HALOutputUnit (Pt 1)
Re: HALOutputUnit (Pt 1)
- Subject: Re: HALOutputUnit (Pt 1)
- From: Bob Stuller <email@hidden>
- Date: Thu, 5 Feb 2004 14:11:51 -0500
Bill, Greetings!
At 5:06 PM -0800 2/4/04, William Stewart wrote:
In the case of a device that doesn't have a in and out (for eg,
USB) the client can register a callback with the AUHAL unit
(kAudioOutputUnitProperty_SetInputCallback) - this then will call
you when the AUHAL unit has input data for you. Please note, due
to some bugs in CA-Panther this WASN'T working as shipped -
however, with the QT 6.5 update we fixed those (so this now works
for Panther and Jaguar
systems)...
A couple of questions. I registered an input callback with element
== 1, the input bus if I understand this right. I get the calls on
my callback routine whether I use Input scope or Output scope.
What is the correct scope? Since I have attached a USB input
device to the HALOutputUnit, I would think that using the wrong
scope would result in an error. Looking at your diagram above &
knowing that I am dealing with an input-only device, I would think
that most anything (except disabling i/o) that I did with bus zero
or the AU's input scope would result in an error, no?
The scope is global (though actually the scope arg is ignored) -
what has to be set is the element == 1 (which actually is ignored as
well :) - but the correct setting (and make sure you do this, so
when we tighten this up you don't get errors) would be: Global
Scope, ElID==1
Okay, this makes a variety of sense: There can only be one
InputCallback per HALOutputUnit. But I guess I should have asked
this more generally. All the way through this section of code this
question arises, e.g. when setting a channel map, clearly the
ElementID should be 1 but, since we're talking about the output side
of the AU, shouldn't the scope argument be Output? While it feels
like it should matter, I am prepared to hear you say that this too is
ignored. B-)
Secondly, I was surprised that the HALOutputUnit didn't provide a
AudioBufferList in the callback. The HALOutputUnit surely has (in
my situation) the converted samples in its own buffer on this side
of the kernel/user-space divide: It seemed like it would provide
that buffer list to cut down on copying. Given that it doesn't and
given that the callback fires in a thread other than my program's
main thread, am I okay calling malloc to allocate buffer space?
This has worked so far but... is it safe? If not, is there a way
to know up front how many frames the callback will be offered?
The callback is there just to tell you that there is input to get.
You then call AudioUnitRender as described in the documents - That's
the *only* path you use to get input.
You don't have to provide buffer space actually (but you can) - it
is perfectly legal to call AudioUnitRender with the mData pointers
in the buffer list set to NULL. Oh, and this is *not* the thread
(the thread you get the callback notification on) to allocate memory
- its the I/O thread of the device you're getting input from.
Of course, at present I only need to call malloc the first time my
callback is called and, theoretically, when the number of frames
changes. I've always seen 512 for numFrames and turned and passed
that as an argument to AudioUnitRender.
I tried setting the mData to nil (& mDataByteSize to zero) and still
got the CannotDoInCurrentContext error & the buffer's fields were not
filled in. I thought that, if the AU filled in the fields, I know if
I'd been filling them incorrectly.
Now that I am providing a filled-out buffer list, AudioUnitRender
is returning kAudioUnitErr_CannotDoInCurrentContext.
From what I can see this is returned when:
don't have any input data to give you
you're asking for too much data (ie. you are asking for a different
number of frames than it has kept from the I/O proc)... Thus, I
wouldn't do sample rate conversion (as this will trip this), and I'd
ask for the exact same number of frames as the device is doing I/O
in.
Whoa! Are you saying that these samples are coming directly from the
device & the HALOutputUnit will _not_ do conversions such as
sample-rate or float->integer? Before starting up the HALOutputUnit,
I called this:
AudioStreamBasicDescription format;
memset(&format, 0, sizeof(AudioStreamBasicDescription));
format.mSampleRate = 16000.0;
format.mBytesPerFrame = 2;
format.mFramesPerPacket = 1;
format.mBytesPerPacket = 2;
format.mChannelsPerFrame = 1;
format.mBitsPerChannel = 16;
format.mFormatID = kAudioFormatLinearPCM;
format.mFormatFlags = kLinearPCMFormatFlagIsBigEndian
| kLinearPCMFormatFlagIsSignedInteger
| kLinearPCMFormatFlagIsPacked
| kLinearPCMFormatFlagIsNonInterleaved;
status = AudioUnitSetProperty(mHALOutInstance,
kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output,
1, &format, sizeof(format));
and now I think that I'm hearing that the HALOutputUnit is only able
to have unconverted audio pulled by my callback's call to
AudioUnitRender. Is that what I am hearing?
We may remove this restriction (and thus do some buffering of the input)...
Ummm... Do you refer here to being able to pull only part of the
frames available as indicated by 'inNumberFrames' or do you mean you
may allow sample-rate conversion? The particular device that I am
talking to, a Plantronics headset, says that it can do the 16khz that
I am looking for... Should I be setting the format above (or best
match??) on the device as well as the HALOutputUnit?
Is there an issue with me passing most of the callback's arguments
as parameters to AudioUnitRender? The bus number looks okay, the
flags are a zero & no other value seems an improvement, the
timestamp would appear to be valid. What am I doing wrong?
I think you're just asking for the wrong number of frames?
What the callback receives as a parameter it passes as an argument to
AudioUnitRender.
Thanks in advance for putting my feet back on the path.
Peace,
Bob
--
As a rule, one should avoid generalizations.
_______________________________________________
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.