2026-07-14 08:34:29 +02:00

219 lines
9.4 KiB
C

// SPDX-License-Identifier: Apache-2.0
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <tactility/freertos/freertos.h>
#include <tactility/error.h>
struct Device;
/**
* @brief Direction of an audio codec operation or capability.
*/
enum AudioCodecDirection {
AUDIO_CODEC_DIR_INPUT = 1,
AUDIO_CODEC_DIR_OUTPUT = 2,
AUDIO_CODEC_DIR_BOTH = 3,
};
/**
* @brief Stream configuration used to open a codec for reading or writing.
*/
struct AudioCodecStreamConfig {
uint32_t sample_rate;
uint8_t bits_per_sample; // 16, 24, 32
uint8_t channels;
enum AudioCodecDirection direction;
};
/**
* @brief API for audio codec drivers (e.g. ES8388, ES7210, AW88298).
*
* Implementations typically wrap a vendor codec library (e.g. esp_codec_dev) and
* the underlying I2S/I2C/GPIO controllers. This API is intentionally low-level and
* codec-agnostic: it does not perform resampling or mixing. Most apps should use
* the higher-level audio_stream API (see audio_stream.h) instead.
*/
struct AudioCodecApi {
/**
* @brief Opens the codec for streaming in the given direction(s).
* @param[in] device the audio codec device
* @param[in] config the stream configuration
* @retval ERROR_NONE on success
* @retval ERROR_NOT_SUPPORTED if the requested direction is not supported
*/
error_t (*open)(struct Device* device, const struct AudioCodecStreamConfig* config);
/**
* @brief Closes the codec, stopping any active streams.
* @param[in] device the audio codec device
* @retval ERROR_NONE on success
*/
error_t (*close)(struct Device* device);
/**
* @brief Reads recorded audio data from the codec. Only valid for codecs opened with input direction.
* @param[in] device the audio codec device
* @param[out] data the buffer to store the read data
* @param[in] data_size the number of bytes to read
* @param[out] bytes_read the number of bytes actually read
* @param[in] timeout the maximum time to wait for the operation to complete
* @retval ERROR_NONE on success
* @retval ERROR_TIMEOUT when the operation timed out
*/
error_t (*read)(struct Device* device, void* data, size_t data_size, size_t* bytes_read, TickType_t timeout);
/**
* @brief Writes audio data for playback to the codec. Only valid for codecs opened with output direction.
* @param[in] device the audio codec device
* @param[in] data the buffer containing the data to write
* @param[in] data_size the number of bytes to write
* @param[out] bytes_written the number of bytes actually written
* @param[in] timeout the maximum time to wait for the operation to complete
* @retval ERROR_NONE on success
* @retval ERROR_TIMEOUT when the operation timed out
*/
error_t (*write)(struct Device* device, const void* data, size_t data_size, size_t* bytes_written, TickType_t timeout);
/**
* @brief Sets the volume for the given direction.
* @param[in] device the audio codec device
* @param[in] direction AUDIO_CODEC_DIR_INPUT or AUDIO_CODEC_DIR_OUTPUT
* @param[in] volume_percent volume in the range 0..100
* @retval ERROR_NONE on success
* @retval ERROR_NOT_SUPPORTED if the direction is not supported by this codec
*/
error_t (*set_volume)(struct Device* device, enum AudioCodecDirection direction, float volume_percent);
/**
* @brief Gets the volume for the given direction.
* @param[in] device the audio codec device
* @param[in] direction AUDIO_CODEC_DIR_INPUT or AUDIO_CODEC_DIR_OUTPUT
* @param[out] volume_percent volume in the range 0..100
* @retval ERROR_NONE on success
* @retval ERROR_NOT_SUPPORTED if the direction is not supported by this codec
*/
error_t (*get_volume)(struct Device* device, enum AudioCodecDirection direction, float* volume_percent);
/**
* @brief Mutes or unmutes the given direction.
* @param[in] device the audio codec device
* @param[in] direction AUDIO_CODEC_DIR_INPUT or AUDIO_CODEC_DIR_OUTPUT
* @param[in] muted true to mute, false to unmute
* @retval ERROR_NONE on success
* @retval ERROR_NOT_SUPPORTED if the direction is not supported by this codec
*/
error_t (*set_mute)(struct Device* device, enum AudioCodecDirection direction, bool muted);
/**
* @brief Gets the mute state for the given direction.
* @param[in] device the audio codec device
* @param[in] direction AUDIO_CODEC_DIR_INPUT or AUDIO_CODEC_DIR_OUTPUT
* @param[out] muted true if muted, false otherwise
* @retval ERROR_NONE on success
* @retval ERROR_NOT_SUPPORTED if the direction is not supported by this codec
*/
error_t (*get_mute)(struct Device* device, enum AudioCodecDirection direction, bool* muted);
/**
* @brief Gets the native sample rate the codec hardware runs at for the given direction.
* @param[in] device the audio codec device
* @param[in] direction AUDIO_CODEC_DIR_INPUT or AUDIO_CODEC_DIR_OUTPUT
* @param[out] rate_hz the native sample rate in Hz
* @retval ERROR_NONE on success
* @retval ERROR_NOT_SUPPORTED if the direction is not supported by this codec
*/
error_t (*get_native_sample_rate)(struct Device* device, enum AudioCodecDirection direction, uint32_t* rate_hz);
/**
* @brief Gets the number of channels the codec hardware natively expects/produces for the
* given direction (e.g. a 4-slot TDM microphone ADC reports 4 here even if an app only
* wants 1). Callers that need a different channel count must downmix/upmix themselves --
* opening the codec with a channel count that doesn't match its native layout can produce
* corrupted audio (e.g. ES7210 in TDM mode silently halves its configured bit depth when
* asked for <= 2 channels).
* @param[in] device the audio codec device
* @param[in] direction AUDIO_CODEC_DIR_INPUT or AUDIO_CODEC_DIR_OUTPUT
* @param[out] channels the native channel count
* @retval ERROR_NONE on success
* @retval ERROR_NOT_SUPPORTED if the direction is not supported by this codec
*/
error_t (*get_native_channels)(struct Device* device, enum AudioCodecDirection direction, uint8_t* channels);
/**
* @brief Gets the directions supported by this codec.
* @param[in] device the audio codec device
* @param[out] supported_directions AUDIO_CODEC_DIR_INPUT, AUDIO_CODEC_DIR_OUTPUT, or AUDIO_CODEC_DIR_BOTH
* @retval ERROR_NONE on success
*/
error_t (*get_capabilities)(struct Device* device, enum AudioCodecDirection* supported_directions);
/**
* @brief Gets a fixed digital gain multiplier to apply to this codec's input samples,
* on top of whatever audio_codec_set_volume() controls. Compensates for mic capsules
* that are quiet even at full hardware gain (e.g. small PDM/MEMS mics), or codecs with
* no working hardware gain control at all (e.g. a dummy PDM codec). Set from the
* codec's own devicetree config; 1.0 (no boost) if this field is NULL or the codec
* doesn't implement it.
* @param[in] device the audio codec device
* @param[out] gain the multiplier to apply (1.0 = no change)
* @retval ERROR_NONE on success
* @retval ERROR_NOT_SUPPORTED if the direction is not supported by this codec
*/
error_t (*get_input_gain_multiplier)(struct Device* device, float* gain);
};
/** @brief See AudioCodecApi::open */
error_t audio_codec_open(struct Device* device, const struct AudioCodecStreamConfig* config);
/** @brief See AudioCodecApi::close */
error_t audio_codec_close(struct Device* device);
/** @brief See AudioCodecApi::read */
error_t audio_codec_read(struct Device* device, void* data, size_t data_size, size_t* bytes_read, TickType_t timeout);
/** @brief See AudioCodecApi::write */
error_t audio_codec_write(struct Device* device, const void* data, size_t data_size, size_t* bytes_written, TickType_t timeout);
/** @brief See AudioCodecApi::set_volume */
error_t audio_codec_set_volume(struct Device* device, enum AudioCodecDirection direction, float volume_percent);
/** @brief See AudioCodecApi::get_volume */
error_t audio_codec_get_volume(struct Device* device, enum AudioCodecDirection direction, float* volume_percent);
/** @brief See AudioCodecApi::set_mute */
error_t audio_codec_set_mute(struct Device* device, enum AudioCodecDirection direction, bool muted);
/** @brief See AudioCodecApi::get_mute */
error_t audio_codec_get_mute(struct Device* device, enum AudioCodecDirection direction, bool* muted);
/** @brief See AudioCodecApi::get_native_sample_rate */
error_t audio_codec_get_native_sample_rate(struct Device* device, enum AudioCodecDirection direction, uint32_t* rate_hz);
/** @brief See AudioCodecApi::get_native_channels */
error_t audio_codec_get_native_channels(struct Device* device, enum AudioCodecDirection direction, uint8_t* channels);
/** @brief See AudioCodecApi::get_capabilities */
error_t audio_codec_get_capabilities(struct Device* device, enum AudioCodecDirection* supported_directions);
/**
* @brief See AudioCodecApi::get_input_gain_multiplier. Returns 1.0 (no change) if the
* codec doesn't implement this field, rather than ERROR_NOT_SUPPORTED -- callers can treat
* the multiplier as always present.
*/
error_t audio_codec_get_input_gain_multiplier(struct Device* device, float* gain);
extern const struct DeviceType AUDIO_CODEC_TYPE;
#ifdef __cplusplus
}
#endif