Capture audio data

Once you've opened and configured a PCM capture device and prepared the PCM subchannel, you're ready to capture sound data.

For more information about this preparation, see Handling PCM devices.

You must set the permissions for your application to allow it to record audio. To set these permissions in the Momentics IDE for BlackBerry, open the project's bar-descriptor.xml file and select the Microphone check box on the Application tab. Alternatively, you can edit the bar-descriptor.xml file by hand to add the record_audio element.

Select what to capture

Most sound cards allow only one analog signal to be connected to the ADC. Therefore, in order to capture audio data, the user or application must select the appropriate input source.

Some sound cards allow multiple signals to be connected to the ADC; in this case, make sure the appropriate signal is one of them. There's an API call, snd_mixer_group_write(), for controlling the mixer so that the application can set this up directly; it's described in the Mixer Architecture chapter.

Capture states

Let's consider the state transitions for PCM devices during capture.

The state diagram for a PCM device during capture is shown below.

State diagram showing state transitions for PCM devices during capture.

The transition between SND_PCM_STATUS_* states is the result of executing an API call, or the result of conditions that occur in the hardware:

From To Cause
NOTREADY READY Calling snd_pcm_channel_params() or snd_pcm_plugin_params()
READY PREPARED Calling snd_pcm_capture_prepare(), snd_pcm_channel_prepare(), or snd_pcm_plugin_prepare()
PREPARED RUNNING Calling snd_pcm_read() or snd_pcm_plugin_read(), calling select() against the capture file descriptors, snd_pcm_channel_go(), or against the capture file descriptors, snd_pcm_capture_go()
RUNNING PAUSED Calling snd_pcm_capture_pause() or snd_pcm_channel_pause()
PAUSED RUNNING Calling snd_pcm_capture_resume(), or snd_pcm_channel_resume()
RUNNING OVERRUN The hardware buffer became full during capture; snd_pcm_read() and snd_pcm_plugin_read() fail
RUNNING UNSECURE The application marked the stream as protected, the hardware level supports a secure transport (e.g., HDCP for HDMI), and authentication was lost
RUNNING CHANGED The stream changed
PAUSED CHANGED The stream changed or an event occurred
PREPARED CHANGED The stream changed or an event occurred
RUNNING ERROR A hardware error occurred
OVERRUN, UNSECURE, CHANGE, or ERROR PREPARED Calling snd_pcm_capture_prepare(), snd_pcm_channel_prepare(), or snd_pcm_plugin_prepare()
RUNNING PREEMPTED Audio is blocked because another libasound session has initiated playback, and the audio driver has determined that that session has higher priority

For more details on these transitions, see the description of each function in the Audio Library chapter.

Receive data from the PCM subchannel

The function that you call to receive data from the subchannel depends on whether or not you're using plugin converters.

The number of bytes read must be a multiple of the fragment size, or the read fails.
The plugin reads an entire fragment from the driver and then fulfills requests for partial reads from that buffer until another full fragment has to be read.

A full nonblocking read mode is supported if the application can't afford to be blocked on the PCM subchannel. You can enable nonblocking mode when you open the handle or by using the snd_pcm_nonblock_mode() API call.

This approach results in a polled operation mode that isn't recommended.

Another method that your application can use to avoid blocking on the read is to use select() to wait until the PCM subchannel has more data. It allows the program to wait on user input while at the same time receiving the capture data from the PCM subchannel.

To get the file descriptor to pass to select(), call snd_pcm_file_descriptor().

With this technique, select() returns when there are frag_size bytes in the subchannel. If your application tries to read more data than this, it may block on the call.

If the PCM subchannel stops during capture

When capturing, the PCM subchannel stops if the hardware has no room for additional data left in its buffer.

This can happen if the application can't consume data at the rate that the hardware is producing data. A real-world example of this is when the application is preempted for a period of time by a higher-priority process. If this preemption continues long enough, the data buffer may be filled before the application can remove any data.

When this happens, the subchannel changes state to SND_PCM_STATUS_OVERRUN. In this state, it won't provide any more data (i.e., snd_pcm_read() and snd_pcm_plugin_read() fail) and the subchannel doesn't restart capturing.

The only ways to move out of this state are to close the subchannel or to reprepare the channel as you did before. This forces the application to recognize and take action to get out of the overrun state; this is primarily for applications that want to synchronize audio with something else. Consider the difficulties involved with synchronization if the subchannel simply were to move back to the SND_PCM_STATUS_RUNNING state from overrun when space became available; the recorded sample would be discontinuous.

Stop capture

If your application wishes to stop capturing, it can simply stop reading data and let the subchannel overrun as described above, but there's a better way.

If you want your application to stop capturing immediately and delete any unread data from the hardware buffer, call one the flush functions:

Synchronize with the PCM subchannel

QSA provides some basic synchronization capabilities.

An application can find out where in the stream the hardware capture position is. The resolution of this position is entirely a function of the hardware driver; consult the specific device driver documentation for details if this is important to your application.

The API calls to get this information are:

Both of these functions fill in a snd_pcm_channel_status_t structure. You'll need to check the following members of this structure:

The hardware capture position, in bytes relative to the start of the stream since you last prepared the channel. The act of preparing a channel resets this count.
The capture position as bytes in the hardware buffer.

The count member isn't used if the mmap plugin is used. To disable the mmap plugin, call snd_pcm_plugin_set_disable().

Last modified: 2014-06-24

Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus