嵌入式音频框架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
相关推荐
雍凉明月夜17 小时前
c++ 精学笔记记录Ⅲ
c++·笔记·学习
(●—●)橘子……17 小时前
记力扣1471.数组中的k个最强值 练习理解
数据结构·python·学习·算法·leetcode
阿蒙Amon17 小时前
JavaScript学习笔记:17.闭包
javascript·笔记·学习
想不出名字ಥ_ಥ17 小时前
STM32学习笔记--01学会如何点亮一颗LED灯
笔记·stm32·学习
لا معنى له18 小时前
学习笔记:循环神经网络(RNN)
人工智能·笔记·学习·机器学习
炒毛豆18 小时前
前端可视化-----svg学习笔记
笔记·学习
暗之星瞳18 小时前
PYTHON学习——决策树
python·学习·随机森林
炽烈小老头18 小时前
【 每天学习一点算法 2025/12/17】验证二叉搜索树
学习·算法
骄傲的心别枯萎18 小时前
RV1126 NO.57:ROCKX+RV1126人脸识别推流项目之读取人脸图片并把特征值保存到sqlite3数据库
数据库·opencv·计算机视觉·sqlite·音视频·rv1126
Century_Dragon18 小时前
在虚拟工位练真技——汽车塑料件拆装修复软件
学习