carb::audio::IAudioCapture

Defined in carb/audio/IAudioCapture.h

struct IAudioCapture

Low-Level Audio Capture Plugin Interface.

See these pages for more detail:

Public Members

size_t (*getDeviceCount)()

retrieves the current audio capture device count for the system.

Note

The device count is a potentially volatile value. This can change at any time, without notice, due to user action. For example, the user could remove an audio device from the system or add a new one at any time. Thus it is a good idea to select the device with setSource() as quickly as possible after choosing the device index. There is no guarantee that the device list will even remain stable during a single device enumeration loop. The only device index that is guaranteed to be valid is the system default device index of 0 (as long as at least one capture device is connected).

Return

the number of audio capture devices that are currently connected to the system or known to the system. The system’s default or preferred device can be found by looking at the flags member of the info structure retrieved from getDeviceCaps(). The default capture device will always be device 0.

AudioResult (*getDeviceCaps)(size_t deviceIndex, DeviceCaps *caps)

retrieves the capabilities and information about a single audio capture device.

Remark

This retrieves information about a single audio capture device. The information will be returned in the caps buffer. This may fail if the device corresponding to the requested index has been removed from the system.

Param deviceIndex

[in] the index of the device to retrieve info for. This must be between 0 and the most recent return value from getDeviceCount().

Param caps

[out] receives the device information. The thisSize value must be set to sizeof(DeviceCaps) before calling.

Retval AudioResult::eOk

if the device info was successfully retrieved.

Retval AudioResult::eOutOfRange

if the requested device index was out of range of devices connected to the system.

Retval AudioResult::eInvalidParameter

if the thisSize value was not initialized in caps or caps was nullptr.

Retval AudioResult::eNotAllowed

if the device list could not be accessed.

Return

an AudioResult error code if the call fails for any other reason.

Context *(*createContext)(const CaptureContextDesc *desc)

creates a new audio capture context object.

Remark

This creates a new audio capture context object. This object is responsible for managing all access to a single instance of the audio capture device. Note that there will be a separate recording thread associated with each instance of the capture context.

Note

If the requested device fails to be set during context creation, the returned context object will still be valid, but it will not be able to capture until a successful call to setSource() returns. This case may be checked upon return using isSourceValid().

Param desc

[in] a descriptor of the initial settings for the capture context. This may be nullptr to create a context that uses the default capture device in its preferred format. The device’s format information may later be retrieved with getSoundFormat().

Return

the newly created audio capture context object if it was successfully created.

Return

nullptr if a new context object could not be created.

AudioResult (*destroyContext)(Context *context)

destroys an audio capture context object.

Remark

This destroys an audio capture context object that was previously created with createContext(). If the context is still active and has a running capture thread, it will be stopped before the object is destroyed. All resources associated with the context will be both invalidated and destroyed as well.

Param context

[in] the context object to be destroyed. Upon return, this object will no longer be valid.

Retval AudioResult::eOk

if the object was successfully destroyed.

Retval AudioResult::eInvalidParameter

if nullptr is passed in.

AudioResult (*setSource)(Context *context, const CaptureDeviceDesc *desc)

selects a capture device and prepares it to begin recording.

Remark

This selects a capture device and sets up the recording buffer for it. The audio will always be captured as uncompressed PCM data in the requested format. The captured audio can be accessed using the lock() and unlock() functions, or with read().

Remark

The length of the buffer would depend on the needs of the caller. For example, if a looping capture is used, the buffer should be long enough that the caller can keep pace with reading the data as it is generated, but not too long that it will introduce an unnecessary amount of latency between when the audio is captured and the caller does something with it. In many situations, a 10-20 millisecond buffer should suffice for streaming applications. A delay greater than 100ms between when audio is produced and heard will be noticeable to the human ear.

Note

If this fails, the state of the context may be reset. This must succeed before any capture operation can be started with captureStart(). All efforts will be made to keep the previous source valid in as many failure cases as possible, but this cannot always be guaranteed. If the call fails, the isSourceValid() call can be used to check whether a capture is still possible without having to call setSource() again.

Note

If this succeeds (or fails in non-recoverable ways mentioned above), the context’s state will have been reset. This means that any previously captured data will be lost and that any previous data format information may be changed. This includes the case of selecting the same device that was previously selected.

Param context

[in] the context object to set the capture source. This context may not be actively capturing data when calling this function. A call to captureStop() must be made first in this case.

Param desc

[in] a descriptor of the device that should be opened and what format the captured data should be in. This may be nullptr to select the system’s default capture device in its preferred format and a default capture buffer size.

Retval AudioResult::eOk

if the requested device was successfully opened.

Retval AudioResult::eNotAllowed

if a capture is currently running.

Retval AudioResult::eOutOfRange

if the requested device index is not valid.

Retval AudioResult::eInvalidFormat

if the requested frame rate or channel count is not allowed.

Return

an AudioResult error code if the device could not be opened.

bool (*isSourceValid)(Context *context)

checks whether a valid capture source is currently selected.

Remark

This checks whether a context’s current source is valid for capture immediately. This can be used after capture creation to test whether the source was successfully selected instead of having to attempt to start a capture then clear the buffer.

Param context

[in] the context to check the capture source on. This may not be nullptr.

Return

true if the context’s currently selected capture source is valid and can start a capture.

Return

false if the context’s source is not valid or could not be selected.

AudioResult (*captureStart)(Context *context, bool looping)

starts capturing audio data from the currently opened device.

Remark

This starts an audio capture on the currently opened device for a context. The audio data will be captured into an internal data buffer that was created with the information passed to the last call to setSource() or when the context was created. The recorded audio data can be accessed by locking regions of the buffer and copying the data out, or by calling read() to retrieve the data as it is produced.

Remark

If the capture buffer is looping, old data will be overwritten after the buffer fills up. It is the caller’s responsibility in this case to periodically check the capture’s position with getCaptureCuror(), and read the data out once enough has been captured.

Remark

If the capture is not looping, the buffer’s data will remain intact even after the capture is complete or is stopped. The caller can read the data back at any time.

Remark

When the capture is started, any previous contents of the buffer will remain and will be added to by the new captured data. If the buffer should be cleared before continuing from a previous capture, the clear() function must be explicitly called first. Each time a new capture device is selected with setSource(), the buffer will be cleared implicitly. Each time the capture is stopped with captureStop() however, the buffer will not be cleared and can be added to by starting it again.

Param context

[in] the context object to start capturing audio from. This context must have successfully selected a capture device either on creation or by using setSource(). This can be verified with isSourceValid().

Param looping

[in] set to true if the audio data should loop over the buffer and overwrite previous data once it reaches the end. Set to false to perform a one-shot capture into the buffer. In this mode, the capture will automatically stop once the buffer becomes full. Note that the cursor position is not reset when capture is stopped, so starting a non-looping capture session will result in the remainder of the buffer being captured.

Retval AudioResult::eOk

if the capture is successfully started.

Retval AudioResult::eDeviceNotOpen

if a device is not selected in the context.

Return

an AudioResult::* error code if the capture could not be started for any other reason.

AudioResult (*captureStop)(Context *context)

stops capturing audio data from the selected device.

Remark

This stops an active audio capture on the currently opened device for a context. The contents of the capture buffer will be left unmodified and can still be accessed with lock() and unlock() or read(). If the capture is started again, it will be resumed from the same location in the buffer as when it was stopped unless clear() is called.

Note

If the capture is stopped somewhere in the middle of the buffer (whether looping or not), the contents of the remainder of the buffer will be undefined. Calling getCaptureCursor() even after the capture is stopped will still return the correct position of the last valid frame of data.

Param context

[in] the context object to stop capturing audio on. This context object must have successfully opened a device either on creation or by using setSource().

Return

AudioResult::eOk if the capture is stopped.

Return

AudioResult::eDeviceNotOpen if a device is not open.

Return

an AudioResult::* error code if the capture could not be stopped or was never started in the first place.

AudioResult (*getCaptureCursor)(Context *context, UnitType type, size_t *position)

retrieves the current capture position in the device’s buffer.

Remark

This retrieves the current capture position in the buffer. This position will be valid even after the capture has been stopped with captureStop(). All data in the buffer up to the returned position will be valid. If the buffer was looping, some of the data at the end of the buffer may be valid as well.

Param context

[in] the context object that the capture is occurring on. This context object must have successfully opened a device either on creation or by using setSource().

Param type

[in] the units to retrieve the current position in. Note that this may not return an accurate position if units in milliseconds or microseconds are requested. If a position in bytes is requested, the returned value will always be aligned to a frame boundary.

Param position

[out] receives the current position of the capture cursor in the units specified by type. All frames in the buffer up to this point will contain valid audio data.

Retval AudioResult::eOk

if the current capture position is successfully retrieved.

Retval AudioResult::eDeviceNotOpen

if no device has been opened.

Return

an AudioResult::* error code if the capture position could not be retrieved.

bool (*isCapturing)(Context *context)

checks whether the context is currently capturing audio data.

Param context

[in] the context object to check the recording state of.

Return

true if the context is currently recording.

Return

false if the context is not recording or no device has been opened.

AudioResult (*lock)(Context *context, size_t length, LockRegion *region)

locks a portion of the buffer to be read.

Remark

This locks a portion of the buffer so that data can be read back. The region may be split into two chunks if the region wraps around the end of the buffer. A non-looping buffer will always be truncated to the end of the buffer and only one chunk will be returned.

Remark

Once the locked region is no longer needed, it must be unlocked with a call to unlock(). Only one region may be locked on the buffer at any given time. Attempting to call lock() twice in a row without unlocking first will result in the second call failing.

Param context

[in] the context object to read data from. This context object must have successfully opened a device either on creation or by using setSource().

Param length

[in] The length of the buffer to lock, in frames. This may be 0 to lock as much data as possible.

Param region

[out] receives the lock region information if the lock operation is successful. This region may be split into two chunks if the region wraps around the end of the buffer. The values in this struct are undefined if the function fails.

Retval AudioResult::eOk

if the requested region is successfully locked.

Retval AudioResult::eDeviceNotOpen

if no device is open.

Retval AudioResult::eNotAllowed

if a region is already locked and needs to be unlocked.

Retval AudioResult::eOverrun

if data has not been read fast enough and some captured data has overwritten unread data.

Return

an AudioResult error code if the region could not be locked.

AudioResult (*unlock)(Context *context)

unlocks a previously locked region of the buffer.

Remark

This unlocks a region of the buffer that was locked with a previous call to lock(). Once the buffer is unlocked, a new region may be locked with lock().

Note

Once the buffer is unlocked, it is not guaranteed that the memory in the region will still be accessible. The caller should never cache the locked region information between unlocks and future locks. The next successful lock call may return a completely different region of memory even for the same offset in the buffer.

Param context

[in] the context object to unlock the buffer on. This context object must have successfully opened a device either on creation or by using setSource().

Retval AudioResult::eOk

if the region is successfully unlocked.

Retval AudioResult::eDeviceNotOpen

if no device has been opened.

Retval AudioResult::eNotAllowed

if no region is currently locked.

Retval AudioResult::eOverrun

if the audio device wrote to part of the locked buffer before unlock() was called.

Return

an AudioResult error code if the region could not be unlocked.

size_t (*calculateReadBufferSize)(Context *context, size_t frameCount)

calculates the required buffer size to store the requested number of frames.

Remark

This is a helper function to calculate the required size in bytes for a buffer to store a requested number of frames. This can be used with read() to ensure a buffer is large enough to store the available number of frames of data.

Param context

[in] the context object to calculate the buffer size for. This context object must have successfully opened a device either on creation or by using setSource().

Param framesCount

[in] the number of frames to calculate the storage space for.

Return

the number of bytes required to store the requested frame count for this context’s current data format.

Return

0 if no device has been selected.

AudioResult (*read)(Context *context, void *buffer, size_t lengthInFrames, size_t *framesRead)

attempts to read captured data from the buffer.

Remark

This provides a means to read the captured audio data as a ‘stream’. This behaves similarly to the libc read() function - it will read data from the current cursor position up to either as much data will fit in the buffer or is currently available to immediately read.

Remark

This may be called with a nullptr buffer and 0 buffer length if only the number of available frames of data is needed. This call method may be used to determine the size of the buffer to pass in or to ensure the buffer is large enough. No actual data will be read and the next call with a non-nullptr buffer will be the one to consume the data. Note that if audio data is still being captured, the number of available frames of data may increase between two consecutive calls. This is fine as only the number of frames that will fit in the output buffer will be consumed and any extra frames that were captured in the meantime can be consumed on the next call. The calcReadBufferSize() function may be used to help calculate the required buffer size in bytes from the available frame count.

Note

It is the caller’s responsibility to call this frequently enough that the capture cursor on a looping buffer will not write over the data that has been read so far. If the capture cursor passes over the read cursor (ie: the last point that the data had been read up to), some corruption in the data may occur when it is finally read again. Data should be read from the buffer with a period of at most half the length of time required to fill the capture buffer.

Note

When this method of reading the captured data is used, it’s not necessary to lock and unlock regions of the buffer. While using this read method may be easier, it may end up being less efficient in certain applications because it may incur some extra processing overhead per call that can be avoided with the use of lock(), unlock(), and getCaptureCursor(). Also, using this method cannot guarantee that the data will be delivered in uniformly sized chunks.

Note

The buffer length and read count must be specified in frames here, otherwise there is no accurate means of identifying how much data will fit in the buffer and how much data was actually read.

Param context

[in] the context object to read data from. This context must have successfully opened a device either upon creation or by using setSource().

Param buffer

[out] receives the data that was read from the capture stream. This may be nullptr if only the available number of frames of data is required. In this case, the available frame count will be returned in the framesRead parameter. The contents of buffer are undefined if this function fails.

Param lengthInFrames

[in] the maximum number of frames of data that can fit in the buffer buffer. It is the caller’s responsibility to know what the device’s channel count is and account for that when allocating memory for the buffer. The size of the required buffer in bytes may be calculated with a call to calculateReadBufferSize(). This will always account for data format and channel count. If buffer is nullptr, this must be set to 0.

Param framesRead

[out] receives the total number of frames of audio data that were read into the buffer. This may be 0 if no new data is available to be read. It is the caller’s responsibility to check this value after return to ensure garbage data is not being processed. It cannot be assumed that the buffer will always be completely filled. The calculateReadBufferSize() helper function can be used to calculate the size of the read data in bytes from this value. This value will not exceed lengthInFrames if buffer is not nullptr. If the buffer is nullptr, this will receive the minimum number of frames currently available to be read.

Retval AudioResult::eOk

if at least one frame of data is successfully read from the buffer.

Retval AudioResult::eTryAgain

if no data was available to read and buffer was not nullptr and no other errors occurred (the value in framesRead will be 0), or if buffer is nullptr and there is data to be read (the number of available frames will be stored in framesRead).

Retval AudioResult::eDeviceNotOpen

if no device has been opened.

Retval AudioResult::eOutOfMemory

if lengthInFrames is 0 and buffer is not nullptr.

Retval AudioResult::eOverrun

if data has not been read fast enough and some captured data has overwritten unread data.

Return

an AudioResult error code if the operation failed for some other reason.

size_t (*getBufferSize)(Context *context, UnitType type)

retrieves the size of the capture buffer in frames.

Remark

This retrieves the actual size of the capture buffer that was created when the context opened its device. This is useful as a way to retrieve the buffer size in different units than it was created in (ie: create in frames but retrieved as time in milliseconds), or to retrieve the size of a buffer on a device that was opened with a zero buffer size.

Remark

If the buffer length is requested in milliseconds or microseconds, it may not be precise due to rounding issues. The returned buffer size in this case will be the minimum time in milliseconds or microseconds that the buffer will cover.

Remark

If the buffer length is requested in bytes, the returned size will always be aligned to a frame boundary.

Param context

[in] the context object to retrieve the buffer size for. This context object must have successfully opened a device either upon creation or by using setSource().

Param type

[in] the units to retrieve the buffer size in.

Return

the size of the capture buffer in the specified units.

Return

0 if a device hasn’t been opened yet.

AudioResult (*getSoundFormat)(Context *context, SoundFormat *format)

retrieves the captured data’s format information.

Remark

This retrieves the data format information for the internal capture buffer. This will identify how the captured audio is intended to be processed. This can be collected to identify the actual capture data format if the device is opened using its preferred channel count and frame rate.

Param context

[in] the context object to retrieve the data format information for. This context object must have successfully opened a device either upon creation or by using setSource().

Param format

[out] receives the data format information. This may not be nullptr.

Retval AudioResult::eOk

if the data format information is successfully returned.

Retval AudioResult::eDeviceNotOpen

if no device has been opened.

Return

an AudioResult error code if any other error occurs.

AudioResult (*clear)(Context *context)

clears the capture buffer and resets it to the start.

Remark

This clears the contents of the capture buffer and resets its cursor back to the start of the buffer. This should only be done when the device is not capturing data. Attempting to clear the buffer while the capture is running will cause this call to fail.

Param context

[in] the context object to clear the buffer on. This context object must have successfully opened a device using setSource().

Retval AudioResult::eOk

if the capture buffer was successfully cleared.

Retval AudioResult::eDeviceNotOpen

if no device has been opened.

Retval AudioResult::eNotAllowed

if the buffer is currently locked or currently capturing.

Return

an AudioResult error code if the operation fails for any other reason.

AudioResult (*getAvailableFrames)(Context *context, size_t *available)

Get the available number of frames to be read.

Param context

[in] The context object to clear the buffer on. This context object must have successfully opened a device using setSource().

Param available

[out] The number of frames that can be read from the buffer.

Retval AudioResult::eOk

if the frame count was retrieved successfully.

Retval AudioResult::eDeviceNotOpen

if no device has been opened.

Retval AudioResult::eOverrun

if data has not been read fast enough and the buffer filled up.

Public Static Functions

static inline constexpr carb::InterfaceDesc getInterfaceDesc() noexcept

Returns information about this interface.

Auto-generated by CARB_PLUGIN_INTERFACE() or CARB_PLUGIN_INTERFACE_EX.

Returns

The carb::InterfaceDesc struct with information about this interface.

static inline constexpr carb::InterfaceDesc getLatestInterfaceDesc() noexcept

Returns information about the latest version of this interface.

Auto-generated by CARB_PLUGIN_INTERFACE() or CARB_PLUGIN_INTERFACE_EX.

Returns

The carb::InterfaceDesc struct with information about the latest version of this interface.