Configuring the PCM device

The next step in playing back or capturing the sound stream is to inform the device of the format of the data that you're about to send it or want to receive from it.

You can do this by filling in a snd_pcm_channel_params_t structure, and then calling snd_pcm_channel_params() or snd_pcm_plugin_params(). The difference between the functions is that the second one uses the plugin converters (see PCM plugin converters in the Audio Architecture chapter) if required.

If the device can't support the data parameters you're setting, or if all the subchannels of the device are currently in use, both of these functions fail.

The API calls for determining the current capabilities of a PCM device are:

Use the plugin converters. If the hardware has a free subchannel, the capabilities returned are extensive because the plugin converters make any necessary conversion.
Access the hardware directly. This function returns only what the hardware capabilities are.
Note: Both of these functions take as an argument a pointer to a snd_pcm_channel_info_t structure. You must set the channel member of this structure to the desired direction (SND_PCM_CHANNEL_CAPTURE or SND_PCM_CHANNEL_PLAYBACK) before calling the functions. The functions fill in the other members of the structure.

It's the act of configuring the channel that allocates a subchannel to the client. Stated another way, hundreds of clients can open a handle to a PCM device with only one subchannel, but only one can configure it. After a client allocates a subchannel, it isn't returned to the free pool until the handle is closed. One result of this mechanism is that, from moment to moment, the capabilities of a PCM device change as other applications allocate and free subchannels. Additionally the act of configuring / allocating a subchannel changes its state from SND_PCM_STATUS_NOTREADY to SND_PCM_STATUS_READY.

If the API call succeeds, then an audio subchannel is acquired based on the provided parameters. The QNX Sound Architecture (QSA), on a best effort basis, uses the fragment size frag_size as requested, but the actual fragment size that's used may differ based on hardware alignment restrictions and potential data conversions that may exist. In the end, you must use the fragment size that's returned from snd_pcm_plugin_setup(). For more information, see the note about fragment sizes in the Optimizing Audio chapter of this guide.

Another aspect of configuration is determining how big to make the hardware buffer. This determines how much latency that the application has when sending data to the driver or reading data from it. The hardware buffer size is determined by multiplying the frag_size by the max_frags parameter, so for the application to know the buffer size, it must determine the actual frag_size that the driver is using.

You can do this by calling snd_pcm_channel_setup() or snd_pcm_plugin_setup(), depending on whether or not your application is using the plugin converters. Both of these functions take as an argument a pointer to a snd_pcm_channel_setup_t structure that they fill with information about how the channel is configured, including the true frag_size.