The DRC microphone API set encapsulates all the pieces that control access to the microphone on the DRC. It manages the state of the driver chain, performs data and sample rate conversion, and matches the sampling frequency used in the audio subsystem (AX) of 32kHz exactly.
To keep data copies to a minimum, the API is designed around a shared ring buffer architecture. APIs exist to query the amount of available samples and to set the number of samples consumed by the audio system. That way, the finite state machine in the microphone driver can properly manage itself as the data source of the ring buffer.
The memory used for the ring buffer is provided by a hierarchically higher-level process, the application. If that application wants to perform DMA directly from that shared ring buffer then it is the application's responsibility to manage buffer alignment and memory coherency.
It is the application's responsibility to check the fill level of the shared ring buffer before drawing from it. PCM data arrives in bursts. Under normal operating conditions where the link with the DRC is intact, bursts of PCM data arrive in 16ms intervals. The microphone driver matches the average incoming data rate to the 32kHz audio sample clock used in the AX subsystem. That is, with a minimum of 32ms of buffered PCM data gapless playback can be assured. This defines a minimum ring buffer size of 2048 bytes which is enforced in the microphone driver.
The design goal of the DRC microphone library is to minimize the amount of software complexity and cost when the streaming of PCM audio samples is in progress. To that end, a rate matching and zero fill algorithm are integrated into the DRC microphone library. The task of the audio rendering loop is to query how many samples are available in the ring buffer, make that memory coherent, i.e., flush the data cache, and inform the DRC microphone library of the number of samples processed in that manner.
In the event that the application does not draw audio samples as quickly as they arrive, then the microphone driver will overwrite the oldest data. That ensures that after the drawing of samples matches the incoming rate, only a single skip occurred.
In the event that the application draws data faster than it arrives, which can be either by design (such as simple pitch-shifting schemes) or due to link loss with the DRC. In those cases an application will read old data that is left in the ring buffer. To avoid this condition an application must query the amount of available data prior to using it for playback.
Link loss with the DRC can occur at any time. It can be in the form of delayed delivery of PCM data, the drop of one or more PCM data packets, or it can reach the level of console and DRC being disconnected. The rate matching algorithm in the DRC microphone library detects when audio packets are overdue and the shared ring buffer is about to underflow. When that is about to happen, all zero samples are put into the buffer. When PCM data from the DRC resume, they are put into the ring buffer as before. Should too many samples arrive, due to the temporary link loss and subsequent catch-up, then the excess is discarded to keep the ring buffer level within its nominal latency.
A link loss may not be temporary. That means that the DRC and console become
disconnected. When that happens, the equivalent of calling
MICClose followed by
MICUninit is automatically performed by the library. The DRC microphone library
implements a policy that when the DRC has become disconnected, the library and
underlying driver stack revert to an uninitialized, quiescent, and closed state.
MICGetStatus indicate the connection state. Attempts to initialize or
open the DRC microphone library will return an error indicating the loss of
The Cafe Core OS (COS) has the concept of foreground and background processes and foreground,
background switching. An application is given notification via the system
message queue. The steps for an orderly switch to background are calling
MICUninit. That will leave the underlying driver stack in a quiescent
state. In the event that an application does not perform those steps, then they
are performed in the DRC microphone library and the DRC microphone sub system will
behave as if it has been disconnected.
Both a return to foreground as well as reconnection require that the DRC microphone library be reinitialized.
The DRC microphone allows for some adjustments, such as the microphone gain. For that
purpose a pair of APIs,
MICSetState, are used to query or set a
given parameter. The turn around time to query or set a particular parameter is on
the order of several milliseconds for most requests. Much of the time is spent
with the executing thread being blocked.
The set and get state APIs, as well as the open and close APIs are inherently slow and should not be called directly from the main drawing loop. It is recommended that applications create a separate thread that performs those slower operations. Most of the time is spent waiting on synchronization objects which means that the actual CPU load created by calling those functions is small.
The driver is meant to be initialized once by calling
At that time the shared memory is provided to the driver and is
used thereafter. That memory needs to be kept writable to the DRC microphone
MICUninit has returned, the
device has become disconnected, or the application has been put into the background.
The streaming of PCM data is started by calling
and stopped by calling
MICClose. Streaming can be
started and stopped as often as the application sees fit. It is not until
MICOpen is called that audio samples can arrive in
the shared buffer.
MICOpen has returned with no error a voice (in AX sense) can be configured to
be used with the ringbuffer filled by the DRC microphone library. Playback through
that ringbuffer requires minimal software intervention.
After streaming is started, the application needs to call
to get the number of PCM samples that are ready in the shared ring buffer. After a
sufficient number of samples is in the buffer, the application is free to consume
them as it sees fit. To keep the ring buffer state between the DRC microphone
library and the application coherent,
the application must inform the driver of the number of samples it has consumed
from the shared ring buffer by calling
Typically, this task of state management is performed within the AX system's callback function. It will also be necessary to make the ring buffer memory coherent before DMA can be performed by flushing the respective portion of the data cache.
MICGetStatus will also return
flags. Those flags indicate whether the driver is 'open' and whether the DRC is
presently connected. After the DRC becomes disconnected, the
bit will no longer be set or the error
MIC_ERROR_NOT_INIT is returned. Both
indicate loss of connection. The error return value indicates that the DRC microphone
library has finished uninitializing.
As soon as a disconnect indication is given, the voice playing the DRC microphone PCM
stream needs to be stopped. If the application wishes to resume DRC microphone sound
playback, it can poll by trying to initialize the DRC microphone library with
until it succeeds.
Since the ring buffer fill matches the nominal 32kHz sample rate of the AX system exactly, it is permissible to derive all microphone playback timing from the AX system generated interrupts. However, the application is strongly encouraged to check that the number of samples available in the buffer is sufficient for the number of samples scheduled for consumption.
MICUninit take several milliseconds to 10s of milliseconds to return, although most of the time is spent waiting on COS synchronization objects.
It is recommended that execution of those APIs be performed in a separate thread that can tolerate such delays.
Connection state notifications are available elsewhere in the system and they are
not duplicated in the DRC microphone library. However, the connection state can
be polled. Calling
MICInit with the DRC disconnected will return
Such polling can be performed within the applications draw loop since the status check or the
actual init operation will execute quickly.
When the headset is either plugged into or unplugged from the DRC headphone jack, an audible 'pop' may be heard. The issue may be especially noticeable for voice chat partners and is hardware specific.
We are planning to extend the
mic_status_t data structure by adding an unsigned integer
variable that shows the number of samples that were generated by zero fill. It is
intended to convey the quality of the link to the application. This counter starts at
zero and is monotonically increasing until
MICUninit is called, the link is lost, or the
application has switched to the background.
2013/05/08 Automated cleanup pass.
2012/06/08 Update to match SDK 2.06.
2011/10/27 Initial version.