Platform Adaptation Layer (PAL)
平台适配层(PAL)提供更高层次的音频特定API,以访问底层音频硬件和驱动程序,从而启用丰富的音频用例。
PulseAudio使用相同的PAL API来处理不同的音频用例。PAL模块的源代码位于:
build-qcom-wayland/workspace/sources/pal/opensource/arpal-lx
PAL模块所暴露的所有API均在以下文件中声明:
build-qcom-wayland/workspace/sources/pal/opensource/arpal-lx/inc/PalApi.h
以下是一些常用的PAL API。
pal_init
初始化PAL,解析相关的配置文件,并将其存储在本地结构中,以便在使用案例期间使用。
int32_t pal_init()
参数
无
返回值
成功返回0
失败返回错误代码
pal_deinit
反初始化PAL,并释放在初始化期间分配的资源。
void pal_deinit()
参数
无
返回值
成功返回0
失败返回错误代码
pal_stream_open
使用指定的配置(如源/接收器设备、媒体配置等)打开一个流。在成功执行时返回流句柄。
int32_t pal_stream_open(
struct pal_stream_attributes *attributes,
uint32_t no_of_devices,
struct pal_device *devices,
uint32_t no_of_modifiers,
struct modifier_kv *modifiers,
pal_stream_callback cb,
uint64_t cookie,
pal_stream_handle_t **stream_handle)
参数
attributes:从 pal_stream_open 获得的有效流属性
no_of_devices:与流初始启动的音频设备数量
devices:pal_devices的数组。数组的大小基于客户端指定的 no_of_devices。
no_of_modifiers:修饰符的数量
modifiers:修饰符数组。修饰符用于添加额外的键值对。
cb:与流关联的回调函数。任何事件将通过此回调函数通知。
cookie:与流关联的客户端数据。此cookie将在回调函数中返回。
stream_handle:如果操作成功,更新为有效流句柄。
返回值
成功返回0
失败返回错误代码
pal_stream_start
启动一个流。
int32_t pal_stream_start(
pal_stream_handle_t *stream_handle)
参数
stream_handle:从 pal_stream_open 获得的有效流句柄
返回值
成功返回0
失败返回错误代码
pal_stream_read
读取从音频源设备捕获的音频缓冲区。
ssize_t pal_stream_read(
pal_stream_handle_t *stream_handle,
struct pal_buffer *buf)
参数
stream_handle:从 pal_stream_open 获得的有效流句柄
buf:指向包含音频样本和元数据的pal_buffer的指针
返回值
读取的字节数
失败返回错误代码
pal_stream_write
为流渲染写入音频缓冲区到接收器设备。
ssize_t pal_stream_write(
pal_stream_handle_t *stream_handle,
struct pal_buffer *buf)
参数
stream_handle:从 pal_stream_open 获得的有效流句柄
buf:指向包含音频样本和元数据的pal_buffer的指针
返回值
写入的字节数
失败返回错误代码
pal_stream_stop
停止一个流。
int32_t pal_stream_stop(
pal_stream_handle_t *stream_handle)
参数
stream_handle:从 pal_stream_open 获得的有效流句柄
返回值
成功返回0
失败返回错误代码
pal_stream_close
关闭一个流。
int32_t pal_stream_close(
pal_stream_handle_t *stream_handle)
参数
stream_handle:从 pal_stream_open 获得的有效流句柄
返回值
成功返回0
失败返回错误代码
TinyALSA
TinyALSA 是一个库,将ALSA内核接口封装为客户端可以调用的API,并提供一个插件接口来模拟ALSA API。
TinyALSA 的源代码可以在以下位置找到:
build-qcom-wayland/workspace/sources/tinyalsa/opensource/tinyalsa
build-qcom-wayland/workspace/sources/tinyalsa/opensource/tinycompress
以下是一些常用的TinyALSA API,完整的API描述请参见开源TinyALSA文档。
pcm_open
用于打开一个PCM音频设备以进行输入和输出操作。初始化PCM设备以便于通信,允许后续进行音频数据的读写操作。
struct pcm *pcm_open(
unsigned int card,
unsigned int device,
unsigned int flags,
struct pcm_config *config)
参数
card:指定卡号
device:指定所选卡中的设备号
flags:配置PCM设备的各种方面的标志
config:用于指定音频流参数的结构变量
返回值
pcm* 句柄
pcm_is_ready
用于检查PCM设备是否准备好进行输入/输出操作。
int pcm_is_ready(struct pcm *pcm)
参数
pcm:指向打开的PCM设备的指针
返回值
成功返回0
失败返回错误代码
pcm_prepare
准备音频设备的输入和输出操作。
int pcm_prepare(struct pcm *pcm)
参数
pcm:指向打开的PCM设备的指针
返回值
成功返回0
失败返回错误代码
pcm_start
用于启动PCM音频设备进行输入和输出操作。
int pcm_start(struct pcm *pcm)
参数
pcm:指向已打开的PCM设备的指针
返回值
成功返回0
失败返回错误代码
pcm_write
用于将音频数据写入音频PCM设备。接受音频数据作为输入,并将其发送到PCM设备进行播放或处理。
int pcm_write(struct pcm *pcm, const void *data, unsigned int count)
参数
pcm:指向已打开的PCM设备的指针
data:要写入的音频数据
count:要写入的音频帧数
返回值
成功返回0
失败返回错误代码
pcm_read
从PCM设备获取音频数据,允许应用程序从麦克风捕获音频数据。
int pcm_read(struct pcm *pcm, void *data, unsigned int count)
参数
pcm:指向已打开的PCM设备的指针
data:要读取的音频数据
count:要读取的音频帧数
返回值
成功返回0
失败返回错误代码
pcm_stop
用于停止PCM音频设备的进一步输入和输出操作。
int pcm_stop(struct pcm *pcm)
参数
pcm:指向已打开的PCM设备的指针
返回值
成功返回0
失败返回错误代码
pcm_close
用于关闭PCM音频设备。这会释放与PCM设备相关的资源并释放内存。
int pcm_close(struct pcm *pcm)
参数
pcm:指向已打开的PCM设备的指针
返回值
成功返回0
失败返回错误代码
基于TinyALSA的应用
要实现TinyALSA的音频用例,请配置虚拟混音器控制。这些控制由混音插件创建,用于设置音频用例图和模块。大多数是基于字节数组,并使用 mixer_ctl_set_array API 进行配置。元数据(称为“PCM100元数据”)使用键值(KV)对进行设置。有关实现细节,请查看 set_agm_audio_intf_metadata API,在以下位置:
build-qcom-wayland/workspace/sources/agm/opensource/agm/plugins/tinyalsa/test/agmmixer.c
/**
* 键值对
*/
struct agm_key_value {
uint32_t key; /**< 键 */
uint32_t value; /**< 值 */
};
/*键值对的示例分配*/
gkv = calloc(num_gkv, sizeof(struct agm_key_value));
ckv = calloc(num_ckv, sizeof(struct agm_key_value));
按照以下设置顺序实现和执行音频用例。基于TinyALSA的agmplay和agmcap工具的示例代码可以在以下位置找到:
build-qcom-wayland/workspace/sources/agm/opensource/agm/plugins/tinyalsa/test.
-
设置音频接口(后端)设备配置,包括采样率、通道、格式和数据格式。
‘CODEC_DMA-LPAIF_WSA-RX-0 rate ch fmt’ 48000 2 2(PCM_16)
-
设置元数据,包括图形键、设备的校准键和DevicePP。
‘CODEC_DMA-LPAIF_WSA-RX-0 metadata’ bytes
-
设置控制以指示后续混音器配置将设置流和StreamPP子图的元数据。零表示后续命令用于流。
‘PCM100 control’ Zero
‘PCM100 metadata’ bytes -
设置控制以指示后续混音器配置将设置DevicePP和stream-device子图的参数。CODEC_DMA-LPAIF_WSA-RX-0表示后续命令用于stream-device。CODEC_DMA-LPAIF_WSA-RX-0 是注册到ALSA ASOC框架的音频接口之一。所有音频接口的列表可以在 /proc/asound/pcm 找到。
‘PCM100 control’ CODEC_DMA-LPAIF_WSA-RX-0
‘PCM100 metadata’ bytes -
检索与流和音频接口之间的给定会话相关的所有标签、模块ID和实例ID。
‘PCM100 getTaggedInfo’ bytes
-
设置控制以指示后续混音器配置将为流子图上的模块设置参数。
‘PCM100 control’ Zero
‘PCM100 setParam’ bytes -
设置控制以指示后续混音器配置将为StreamDevice和DevicePP子图上的模块设置参数。
‘PCM100 control’ CODEC_DMA-LPAIF_WSA-RX-0
‘PCM100 setParam’ bytes -
将前端(流)与后端(编解码器/音频接口)连接。
‘PCM100 connect’ CODEC_DMA-LPAIF_WSA-RX-0
-
初始化PCM设备以进行通信。
pcm_open
-
准备音频设备以进行输入和输出操作。
pcm_prepare
-
启动PCM音频设备进行输入/输出操作。
pcm_start
-
从音频PCM设备读/写音频数据。
pcm_write/pcm_read
-
停止PCM设备进一步进行输入/输出操作。
pcm_stop
-
关闭PCM音频设备。
pcm_close
所有虚拟设备的混音器控制都可以使用以下命令获取:
ssh root@ip-addr
systemctl stop pulseaudio
tinymix set -D 100
TinyALSA级播放和录音测试
录音
-
要验证使用TinyALSA的录音功能:
ssh root@ip-addr systemctl stop pulseaudio tinymix set 'VA DMIC MUX0' DMIC0 tinymix set 'VA_AIF1_CAP Mixer DEC0' 1 tinymix set 'VA_DEC0 Volume' 100 agmcap /opt/test.wav -D 100 -d 101 -c 1 -r 48000 -b 16 -i CODEC_DMA-LPAIF_VA-TX-0 -dkv 0xA3000004 -skv 0xB1000009 -dppkv 0 -ikv 0 -T 10
-
要提取录制的文件,请在主机机器上运行以下命令:
scp root@[ip-addr]:/data/test.wav
播放
-
要进行播放,首先使用以下命令将 .wav 文件推送到设备:
scp test.wav root@[ip-addr]:/data/
-
运行以下命令以启动播放:
ssh root@ip-addr mount -o remount,rw / systemctl stop pulseaudio scp test.wav root@[ip-addr]:/data/ ssh root@ip-addr tinymix set 'SpkrLeft PA Volume' 20 tinymix set 'WSA RX0 MUX' AIF1_PB tinymix set 'WSA_RX0 INP0' RX0 tinymix set 'WSA_COMP1 Switch' 1 tinymix set 'SpkrLeft WSA MODE' 0 tinymix set 'SpkrLeft COMP Switch' 1 tinymix set 'SpkrLeft BOOST Switch' 1 tinymix set 'SpkrLeft DAC Switch' 1 tinymix set 'SpkrLeft VISENSE Switch' 0 tinymix set 'WSA_RX0 Digital Volume' 85 tinymix set 'SpkrRight WSA MODE' 0 tinymix set 'SpkrRight PA Volume' 20 tinymix set 'WSA RX1 MUX' AIF1_PB tinymix set 'WSA_RX1 INP0' RX1 tinymix set 'WSA_COMP2 Switch' 1 tinymix set 'SpkrRight COMP Switch' 1 tinymix set 'SpkrRight BOOST Switch' 1 tinymix set 'SpkrRight DAC Switch' 1 tinymix set 'SpkrRight VISENSE Switch' 0 tinymix set 'WSA_RX1 Digital Volume' 85 agmplay /opt/test.wav -D 100 -d 100 -i CODEC_DMA-LPAIF_WSA-RX-0