1. PCM 流控制函数
打开、关闭及状态检查
-
pcm_open(unsigned int card, unsigned int device, unsigned int flags, struct pcm_config *config)
打开指定声卡(card)和设备(device)的 PCM 流。- flags 参数确定流的方向:例如
PCM_IN
(录音)或PCM_OUT
(回放)。 - config 参数为一个结构体,内含通道数、采样率、数据格式、周期大小与周期数等设置。
- 成功后返回一个
struct pcm *
句柄,用于后续的数据传输操作。
- flags 参数确定流的方向:例如
-
pcm_close(struct pcm *pcm)
关闭之前通过pcm_open()
打开的 PCM 句柄,释放资源。 -
pcm_is_ready(struct pcm *pcm)
判断 PCM 流是否已成功打开并处于可用状态。返回非零表示出错或不可用,通常在打开后立即检查以确保后续操作是安全的。
2. PCM 参数管理函数
为了判断硬件支持哪些采样参数,你可以获取 PCM 的能力信息:
-
pcm_params_get(unsigned int card, unsigned int device, unsigned int flags)
获取指定 PCM 设备的参数集合,返回一个struct pcm_params *
。该结构体中包含了硬件支持的采样率、格式、周期大小等参数范围。 -
pcm_params_free(struct pcm_params *pcm_params)
释放由pcm_params_get()
分配的参数信息结构体。 -
参数查询和设置函数:
pcm_params_get_mask(struct pcm_params *pcm_params, enum pcm_param param)
获取某个参数(如采样率、格式)的支持情况(一个 bit mask)。pcm_params_get_min()
/pcm_params_get_max()
分别获取某个参数所支持的最小或最大值。pcm_params_set_min()
/pcm_params_set_max()
为参数设置新的最小或最大值(一般用于定制或者限制范围)。
-
pcm_params_to_string(struct pcm_params *params, char *string, unsigned int size)
将参数信息转换为人类可读的字符串,便于调试或者日志输出。返回填充字符串的长度或所需的长度。 -
pcm_params_format_test(struct pcm_params *params, enum pcm_format format)
检查特定的 PCM 格式(例如 PCM_FORMAT_S16_LE)是否在支持的格式中,返回 1 表示支持,0 表示不支持。
3. PCM 配置操作
有时需要在流打开后获取或调整当前使用的配置:
-
pcm_get_config(struct pcm *pcm, struct pcm_config *config)
从已打开的 PCM 流中获取当前的配置信息(例如实际启用的通道数、采样率、缓冲区设置等)。 -
pcm_set_config(struct pcm *pcm, struct pcm_config *config)
修改已经打开的 PCM 流的配置(如果硬件和驱动支持动态调整的话)。
4. 错误信息、格式转换及辅助函数
-
pcm_get_error(struct pcm *pcm)
返回一个字符串,描述最近一次调用出错时的错误原因,用于调试和错误处理。 -
pcm_format_to_bits(enum pcm_format format)
返回所使用 PCM 格式的存储位数。例如,对于PCM_FORMAT_S24_LE
,可能返回 32,因为实际存储 32 位数据(尽管只有 24 位有效)。 -
缓冲区大小转换函数:
pcm_get_buffer_size(struct pcm *pcm)
得到当前 PCM 流推荐使用的总缓冲区大小(单位:帧)。通常总帧数 =period_size * period_count
。pcm_frames_to_bytes(struct pcm *pcm, unsigned int frames)
将帧数转换为字节数(考虑到每帧的采样数据大小,依赖通道数和采样格式)。pcm_bytes_to_frames(struct pcm *pcm, unsigned int bytes)
将字节数转换回帧数。
-
pcm_get_latency(struct pcm *pcm)
返回当前 PCM 流的延迟(以毫秒为单位)。延迟值与缓冲区配置(总大小、采样率等)直接相关。 -
pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail, struct timespec *tstamp)
获取当前缓冲区状态——返回流中可用帧数以及与之关联的时间戳。- 对于输入流,这表示可供应用读取的帧数。
- 对于输出流,这表示还空闲(可写)的帧数。
-
pcm_get_subdevice(struct pcm *pcm)
返回实际打开时使用的子设备编号,有些硬件可能提供多个子设备用于并发操作。
5. 数据传输操作
标准读写接口
-
pcm_read(struct pcm *pcm, void *data, unsigned int count)
从 PCM 输入流(或录音设备)中读取数据。- count 参数通常是以字节为单位,读取的数据量应与
pcm_frames_to_bytes()
计算出的单个周期数据一致。 - 返回值为 0 表示成功,否则返回负值错误码。
- count 参数通常是以字节为单位,读取的数据量应与
-
pcm_write(struct pcm *pcm, const void *data, unsigned int count)
将数据写入 PCM 输出流(或播放设备):- 类似于
pcm_read()
,count
表示写入的数据量(单位:字节)。 - 写入操作会触发硬件播放,如果处于中断恢复状态时(例如 FIFO underrun 后)可能会重新启动播放。
- 类似于
内存映射(mmap)接口
直接使用内存映射技术可以降低数据传输的延迟和 CPU 占用:
pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset, unsigned int *frames)
获取 PCM 设备内存映射缓冲区的起始地址、当前偏移量以及可操作的帧数。pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames)
提交写入或读取的数据,更新缓冲区状态。pcm_mmap_write()
与pcm_mmap_read()
分别用于直接向缓冲区写数据或从缓冲区读取数据,代替标准的pcm_write()
与pcm_read()
。pcm_mmap_avail(struct pcm *pcm)
返回当前缓冲区中可供写入或读取的帧数。pcm_mmap_get_hw_ptr(struct pcm* pcm, unsigned int *hw_ptr, struct timespec *tstamp)
获取当前硬件指针的位置以及它所对应的时间戳,用于同步时钟或进一步的数据处理。
6. 流状态控制和事件接口
-
pcm_prepare(struct pcm *pcm)
准备 PCM 子流,使其处于可触发状态。常用于在播放或录音前执行预处理(例如重置缓冲区)。 -
pcm_start(struct pcm *pcm)
启动 PCM 子流进行数据传输,适用于那些不自动启动数据传输的设备或在调用pcm_write()
/pcm_read()
之前要明确启动的数据流。 -
pcm_stop(struct pcm *pcm)
停止 PCM 子流的数据传输,常用于结束一段播放或录音过程。 -
pcm_ioctl(struct pcm *pcm, int request, ...)
通过 ioctl 调用发送控制命令给 PCM 驱动,允许更底层的控制和调整,这是更底层的设备操作接口。 -
事件与等待相关:
pcm_wait(struct pcm *pcm, int timeout)
等待 PCM 设备准备好数据(例如,等待缓冲区有足够数据可读或者有足够空闲帧可写)。pcm_get_poll_fd(struct pcm *pcm)
得到可以用于poll()
或select()
的文件描述符,以便与其他事件循环集成。pcm_set_avail_min(struct pcm *pcm, int avail_min)
修改在触发 PCM 数据传输前,缓冲区最小应达到的帧数。如果使用 MMAP 模式而且禁用了 IRQ,此设置尤其重要用于降低延迟。
7. Mixer(混音器)控制接口
TinyALSA 同时提供了对硬件混音器的基本控制接口,用于调整音量、开关、通道切换等。
打开、关闭及 Mixer 信息
mixer_open(unsigned int card)
打开指定声卡的混音器设备,返回表示 mixer 的句柄结构。mixer_close(struct mixer *mixer)
关闭并释放混音器资源。mixer_get_name(struct mixer *mixer)
获取混音器的名称,通常用于调试或显示硬件信息。
获取混音器控制(Control)
mixer_get_num_ctls(struct mixer *mixer)
返回混音器中包含多少个可控的控件。mixer_get_ctl(struct mixer *mixer, unsigned int id)
与mixer_get_ctl_by_name(struct mixer *mixer, const char *name)
通过控件的索引或名称获取某个具体的混音器控制对象。mixer_ctl_get_name(struct mixer_ctl *ctl)
获取某个混音器控制项的名称。
混音器控件的属性与操作
-
类型和枚举检查:
mixer_ctl_get_type()
/mixer_ctl_get_type_string()
返回控制项的数据类型(例如整数、布尔值、枚举等)。mixer_ctl_get_num_values(struct mixer_ctl *ctl)
一个控制项可能有多个值,返回值的数量。mixer_ctl_get_num_enums()
与mixer_ctl_get_enum_string()
针对枚举类型的控制项,获取枚举数目及对应的字符串名称。
-
控件数据的获取与设置:
mixer_ctl_get_value()
与mixer_ctl_set_value()
用于直接获取或设置控制项的具体值。mixer_ctl_get_percent()
与mixer_ctl_set_percent()
针对音量等控件,允许以百分比形式获取或设置值。mixer_ctl_get_array()
与mixer_ctl_set_array()
用于读取或设置控件的数组数据(适合多通道或复合控件)。mixer_ctl_set_enum_by_string()
针对枚举控件,通过输入字符串来设置控制值。
-
范围控制:
mixer_ctl_get_range_min()
/mixer_ctl_get_range_max()
获取混音器控件支持的最小或最大值,这对限制控制设置非常有用。
混音器事件支持
mixer_subscribe_events(struct mixer *mixer, int subscribe)
允许应用订阅或取消订阅混音器事件(例如,外部变化触发控制更新)。mixer_wait_event(struct mixer *mixer, int timeout)
等待混音器事件的发生。mixer_consume_event(struct mixer *mixer)
消费已经发生的事件,确保事件不会被重复处理。
小结
- PCM 流相关的函数(
pcm_open
、pcm_close
、pcm_read
、pcm_write
等)主要负责数据传输的初始化、实时读写操作及状态管理。 - 参数管理、配置和转换函数(例如
pcm_params_get
、pcm_frames_to_bytes
等)帮助开发者在运行时查询硬件能力、进行单位转换以及调试配置。 - 高级数据传输接口(如
pcm_mmap_*
系列函数)提供了直接内存映射方式,可用于降低延迟和优化性能。 - Mixer 接口 则提供了对硬件混音器(如音量、通道路由、开关等)的操作,以便对声音输入输出进行更细粒度的控制。