嵌入式音频框架alsa学习之pcm状态

cpp 复制代码
/** PCM state */
typedef enum _snd_pcm_state {
	/** Open */
	SND_PCM_STATE_OPEN = 0,
	/** Setup installed */ 
	SND_PCM_STATE_SETUP,
	/** Ready to start */
	SND_PCM_STATE_PREPARED,
	/** Running */
	SND_PCM_STATE_RUNNING,
	/** Stopped: underrun (playback) or overrun (capture) detected */
	SND_PCM_STATE_XRUN,
	/** Draining: running (playback) or stopped (capture) */
	SND_PCM_STATE_DRAINING,
	/** Paused */
	SND_PCM_STATE_PAUSED,
	/** Hardware is suspended */
	SND_PCM_STATE_SUSPENDED,
	/** Hardware is disconnected */
	SND_PCM_STATE_DISCONNECTED,
	SND_PCM_STATE_LAST = SND_PCM_STATE_DISCONNECTED,
	/** Private - used internally in the library - do not use*/
	SND_PCM_STATE_PRIVATE1 = 1024
} snd_pcm_state_t;

1. SND_PCM_STATE_OPEN

  • 含义:PCM 设备已打开,但尚未配置任何硬件参数(如采样率、格式等)。
  • 触发场景 :调用 snd_pcm_open() 打开设备后的初始状态。

2. SND_PCM_STATE_SETUP

  • 含义 :硬件参数已安装(通过 snd_pcm_hw_params() 设置),但尚未准备好传输数据。
  • 触发场景 :调用 snd_pcm_hw_params() 成功配置参数后进入此状态。

3. SND_PCM_STATE_PREPARED

  • 含义:设备已准备好开始传输数据(如播放或录制),但尚未开始运行。
  • 触发场景 :调用 snd_pcm_prepare() 后进入此状态,此时可以安全地启动数据传输。

4. SND_PCM_STATE_RUNNING

  • 含义:设备正在活跃地处理数据(例如正在播放音频或录制输入)。
  • 触发场景 :调用 snd_pcm_start() 后,设备开始运行。

5. SND_PCM_STATE_XRUN

  • 含义 :发生了 underrun(播放时缓冲区数据不足)overrun(录制时缓冲区已满),导致设备停止。
  • 触发场景
    • 播放场景:应用程序未及时填充数据,导致缓冲区耗尽。
    • 录制场景:应用程序未及时读取数据,导致缓冲区溢出。
  • 处理方式 :需调用 snd_pcm_prepare()snd_pcm_recover() 恢复设备。

6. SND_PCM_STATE_DRAINING

  • 含义:设备正在排空缓冲区中剩余的数据(仅适用于播放模式)。
  • 触发场景 :调用 snd_pcm_drain() 后,设备停止新数据写入,但会继续播放缓冲区中的剩余数据。

7. SND_PCM_STATE_PAUSED

  • 含义:设备被显式暂停(例如用户手动暂停播放)。
  • 触发场景 :调用 snd_pcm_pause() 并设置暂停标志为 1

8. SND_PCM_STATE_SUSPENDED

  • 含义:硬件因系统事件(如进入省电模式)被挂起。
  • 触发场景:系统电源管理事件(如休眠)导致设备暂停。

9. SND_PCM_STATE_DISCONNECTED

  • 含义:物理设备已断开连接(例如 USB 音频设备被拔出)。
  • 触发场景:硬件被物理移除或断开。

10. SND_PCM_STATE_PRIVATE1

  • 含义:ALSA 库内部使用的私有状态,开发者无需关注。
  • 用途:用于 ALSA 内部实现,用户代码中不应依赖此状态。

状态转换示意图

复制代码
OPEN → SETUP → PREPARED → RUNNING → (XRUN/DRAINING/PAUSED/SUSPENDED) → ... → DISCONNECTED

常见问题

Q1: 如何检测并处理 XRUN 状态?
  • 调用 snd_pcm_state() 检查状态,若为 XRUN,需恢复设备:

    复制代码
    if (snd_pcm_state(pcm_handle) == SND_PCM_STATE_XRUN) {
        snd_pcm_prepare(pcm_handle);  // 或 snd_pcm_recover()
    }
Q2: DRAININGPAUSED 的区别?
  • DRAINING:设备正在播放剩余数据(仅播放模式)。
  • PAUSED:设备完全停止,不会继续处理数据,需显式恢复。
Q3: 如何强制停止设备?
  • 调用 snd_pcm_drop() 立即停止设备并丢弃缓冲区数据,状态回到 SETUP
相关推荐
byxdaz4 分钟前
ffmpeg+QOpenGLWidget显示视频
ffmpeg·音视频
郭逍遥19 分钟前
GZCTF平台搭建及题目上传
笔记·学习·ubuntu·docker·容器
吱屋猪_1 小时前
MyBatis 学习经验分享
经验分享·学习·mybatis
落笔画忧愁e3 小时前
数据通信学习笔记之OSPF其他内容1
笔记·学习
GHL2842710903 小时前
mysql学习-B+树相关问题
b树·学习·mysql
Hugging Face4 小时前
SmolVLM2: 让视频理解能力触手可及
音视频
中草药z4 小时前
【RabbitMQ高级特性】消息确认机制、持久化、发送方确认、TTL和死信队列
java·学习·rabbitmq·java-rabbitmq·持久化·高级特性
云上艺旅4 小时前
K8S学习之基础四十六:k8s中部署Kibana
学习·云原生·容器·kubernetes
weixin_502539854 小时前
rust学习笔记18-迭代器
笔记·学习·rust
GoldenaArcher4 小时前
lodash 学习笔记/使用心得
javascript·笔记·学习