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.
Let's consider the state transitions for PCM devices during capture.
The state diagram for a PCM device during capture is shown below.
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:
|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.
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