Re: in & out Callbacks
Re: in & out Callbacks
- Subject: Re: in & out Callbacks
- From: Jeff Moore <email@hidden>
- Date: Mon, 14 Feb 2005 14:57:09 -0800
On Feb 14, 2005, at 2:04 PM, Lubor Prikryl wrote:
Hello Jeff and others who are interested,
On 14.2.2005, at 21:00, Jeff Moore wrote:
Have you looked for the cause of your glitching? If you haven't
pinned it down precisely, you probably should because 9 times out of
10 it's not what you think it is, especially if you are trying to
synchronize multiple threads.
Actually, I don't try to synchronize audio threads. But I have some
suspicion that the thread handling I/O for USB (if it were any) is
not synchronized properly with the audio thread. Is it possible?
They are never synchronized with each other. This decoupling of what
the driver/hardware is doing from what the application is doing is part
of the whole architecture of the system.
That said, I'm a bit puzzled by what you are trying to accomplish.
It sounds to me like you are trying to take input received from one
device, process it, and put it out on another device, which
necessitates synchronizing the two IO threads. Yes?
Probably not. Input and output callbacks from ONE device run in ONE
thread, (I dont list threads I have created, MIDI and event loop)
Actually by definition, it does. I was being slightly facetious by
asking the question.
Thread 1a
#0 0x00020560 in InputAudioCallback(unsigned long, AudioTimeStamp
const*, AudioBufferList const*, AudioTimeStamp const*,
AudioBufferList*, AudioTimeStamp const*, void*) at RTHAL.cpp:1065
#1 0x9072360c in IOADevice::CallIOProcs(AudioTimeStamp const&,
AudioTimeStamp const&, AudioTimeStamp const&)
#2 0x90723a60 in HPIOThread::PerformIO(AudioTimeStamp const&)
#3 0x90722c14 in HPIOThread::WorkLoop()
#4 0x9073919c in HPIOThread::ThreadEntry(HPIOThread*)
#5 0x907391e0 in CAPThread::Entry(CAPThread*)
#6 0x900246e8 in _pthread_body
the same thread 1b
#0 0x0001f64c in OutputAudioCallback(unsigned long, AudioTimeStamp
const*, AudioBufferList const*, AudioTimeStamp const*,
AudioBufferList*, AudioTimeStamp const*, void*) at RTHAL.cpp:853
#1 0x9072360c in IOADevice::CallIOProcs(AudioTimeStamp const&,
AudioTimeStamp const&, AudioTimeStamp const&)
#2 0x90723a60 in HPIOThread::PerformIO(AudioTimeStamp const&)
#3 0x90722c14 in HPIOThread::WorkLoop()
#4 0x9073919c in HPIOThread::ThreadEntry(HPIOThread*)
#5 0x907391e0 in CAPThread::Entry(CAPThread*)
#6 0x900246e8 in _pthread_body
These are the two IO threads the HAL manages for the two devices you
are using. The first one is obviously the one you are using for input
while the second is being used for output.
Thread 2
#0 0x900074c8 in mach_msg_trap
#1 0x90007018 in mach_msg
#2 0x90191700 in __CFRunLoopRun
#3 0x90195e8c in CFRunLoopRunSpecific
#4 0x90732f80 in HALRunLoop::OwnThread(void*)
#5 0x907391e0 in CAPThread::Entry(CAPThread*)
#6 0x900246e8 in _pthread_body
This is the HAL's notification thread. It is created and managed by the
HAL to facilitate receiving notifications from drivers. Applications
can tell the HAL to use a different thread via the system property,
and Thread 3
#0 0x900074c8 in mach_msg_trap
#1 0x90007018 in mach_msg
#2 0x90191700 in __CFRunLoopRun
#3 0x90195e8c in CFRunLoopRunSpecific
#4 0x901ff328 in CFRunLoopRun
#5 0x077142bc in
AVS::DestroyAVCDeviceController(AVS::AVCDeviceController*)
#6 0x900246e8 in _pthread_body
I'm not sure what this thread is for. It might be the iSight. Whatever
it is, it is either totally uninvolved with audio IO or only
peripherally involved.
Jeff, my questions are here:
- What the latter two threads do?
They are the HAL's IO threads. The HAL creates one per audio device per
process.
- Are the two Callbacks 1a and 1b always guaranteed to be called
exactly alternating i-o-i-o-i-o-i-o... if running in one thread?
Absolutely not. While they will for the most part stay in the order
that they initially are called, the threads are working for two
different devices and as such have totally different time lines. They
can easily drift to the point where the order of calling can be
inverted. Plus, if their duty cycles dictate that they are to wake up
at times that are close together, the order of operations will be
essentially random each time.
This is why I talked about using AudioDeviceStartAtTime(). It doesn't
cure the drift problem, but it does give you the ability to phase the
threads in the order in which you want them, with the approximate
timing you want.
- For the USB class driver, 1a and 1b are TWO threads just as for
physically different devices, so should I synchronize them manually?
The USB Audio Class spec defines the input side of a device as being
wholly separate from the output side for purposes of timing. This means
that you have to assume that the input and output are not synchronized
together in the hardware. They can and do drift from one another.
This also means that they have to be treated as separate audio devices
by the HAL and thus have to use separate IO threads.
The third question implies:
- How can I handle I/O using HAL Output AU, when input and output are
divided in two devices for the USB class driver?
You need two individual instances of AUHAL, one per device. Then you
have to write the code that bridges the input data to the output.
I think, depending on these answers I will have or won't have to
follow your suggestions below.
Thanks
Lubor
First off, I'd look very closely at how you are synchronizing the
threads. If there are mutexes involved, I'd check them thoroughly to
be sure that the IO thread can never, ever block on them. Otherwise,
you will glitch.
Next, as you surmise, you can't directly control the phasing of the
two IO threads with AudioDeviceStart(). You need to use
AudioDeviceStartAtTime() to do that. This allows you to set things
up so that the input device's IO thread runs out of phase with the
output device's IO thread by making them start at particular times
using IO buffer sizes that represent the same amount of time. This
allows you to be sure that the input is delivered before the output.
The only problem you'll have with that scheme is drift over time if
the input device is not synchronized with the output device in
hardware. The drift will slowly shift the phase between the input
and output threads until they eventually coincide. The speed at
which this happens depends on the rate scalar between the devices.
The only way to fix it would be to periodically stop and restart
things.
On Feb 12, 2005, at 9:53 AM, Lubor Prikryl wrote:
Hi,
My app is processing a stack of effects. I did the following:
- in the input callback I copied data from mBuffers[].mData to my
buffers
- in the output callback I processed the data and copied them back
to mBuffers[].mData
On certain systems generally with higher CPU load (but NOT
overload) my application clicks and pops from time to time.
To fix it, I changed to this:
- in the input callback I do nothing
- all the work was done in the output callback
My questions:
- What is better? (I think the second, but it cannot be used
generally)
- For the first approach, is it guaranteed that callbacks are
called exactly i-o-i-o-i-o-i-o-i-o-i-o... for one device? (I
perform checking, it actually seems to be regular)
- The second approach can't be used with USB class driver or with
two externally synced devices unless I would establish circular
buffers and increase latency. I expect some non-regular alternating
here, correct?
- If I would replace the AudioDeviceAddIOProc based HAL i/o by an
AudioUnit i/o, I would get to the bad situation with the usb class
compliant driver and externally synchronized devices, I would open
two AUs to handle, but only one i/o AU is allowed per one Graph.
Thanks for a hint
Lubor
--
Jeff Moore
Core Audio
Apple
_______________________________________________
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